2020牛客寒假算法基礎集訓營2【A - J】

題目來源:https://ac.nowcoder.com/acm/contest/3003#question
這場就比較菜了,差點拿了一血,但是…就差一點點 點點點 實力是六題,因爲有一題數據弱了… 先寫着幾個水題的題解,之後再補(可能明天)
UPD:補完了~


A - 做遊戲

看代碼都能懂

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
template<class T>
inline void read(T &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
int main()
{
    LL a,b,c,x,y,z;
    rrr(a,b,c); rrr(x,y,z);
    cout<<min(x,c)+min(y,a)+min(z,b)<<endl;
    return 0;
}


B - 排數字

統計6 和 1出現的次數 ,設分別爲a b ,那麼答案就是max(min(a-1,b),0)
因爲最簡排法是 616161616 這樣子

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
char s[N];
template<class T>
inline void read(T &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
int main()
{
    r(n);
    int cnt1=0,cnt6=0;
    scanf("%s",s+1);
    FOR(i,1,n){
        if(s[i]=='1') cnt1++;
        else if(s[i]=='6') cnt6++;
    }
    cout<<max(0,min(cnt6-1,cnt1))<<endl;
    return 0;
}


C - 算概率

設dp[ i ][ j ]爲前i道題做出來j道的概率,可以在複雜度O(n2)內解決
轉移方程爲:dp[i][j]=(dp[i-1][j]*(1-f[i])+dp[i-1][j-1]*f[i]);

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
LL dp[M][M];
LL f[N];
template<class T>
inline void read(T &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
int main()
{
    r(n);
    FOR(i,1,n){r(f[i]);}
    dp[0][0]=1;
    FOR(i,1,n){
        dp[i][0]=dp[i-1][0]*(1-f[i]+mod)%mod;
        FOR(j,1,i){
            dp[i][j]=(dp[i-1][j]*(1-f[i]+mod)%mod+dp[i-1][j-1]*f[i]%mod)%mod;
        }
    }
    FOR(i,0,n) cout<<dp[n][i]<<' ';
    cout<<endl;
    return 0;
}

D - 數三角

暴力,枚舉三角形的三個點 a b c 通過向量乘積的正負判斷是否有鈍角 即可
但是要注意 三點一線的特判 if(xx*yyy==yy*xxx) return 0;

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
struct point
{
    int x,y;
}f[N];
template<class T>
inline void read(T &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
bool hhh(point a,point b,point c)
{
    int xx=b.x-a.x,yy=b.y-a.y;
    int xxx=c.x-a.x,yyy=c.y-a.y;
    if(xx*yyy==yy*xxx) return 0;
    return (xx*xxx+yy*yyy)<0;
}
int main()
{
    r(n);
    FOR(i,1,n){
        scanf("%d%d",&f[i].x,&f[i].y);
    }
    int ans=0;
    FOR(i,1,n){
        FOR(j,i+1,n){
            FOR(k,j+1,n){
                point a=f[i];
                point b=f[j];
                point c=f[k];
                if(hhh(a,b,c)||hhh(b,c,a)||hhh(c,b,a)){
                    ans++;
                }
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}


E - 做計數

這題也算暴力吧。 首先兩邊平方 得到 i + j + sqrt(ij) = k
我們知道 i j k 都是整數 ,如果i
j不能開方出整數 那肯定不行
所以枚舉n以內所有的平方數 1 4 9 …
然後再統計這個平方數的因子即可

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
template<class T>
inline void read(T &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
int main()
{
    r(n);
    LL ans=0;
    FOR(i,1,n){
        int t=sqrt(i);
        if(t*t==i){
            FOR(j,1,t){
                if(i%j==0){
                    if(j==t) ans++;
                    else ans+=2;
                }
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}


F - 拿物品

拿的物品a多或者b多對自己都是有好處的,效果相同。
我們以a+b的大小從大到小排序 正着取即可

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
struct node
{
    int a,b,id;
}f[N];
bool cmp(node a,node b)
{
    return a.a+a.b>b.a+b.b;
}
template<class T>
inline void read(T &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
int main()
{
    r(n);
    FOR(i,1,n){
        r(f[i].a);
        f[i].id=i;
    }
    FOR(i,1,n) r(f[i].b);
    sort(f+1,f+n+1,cmp);
    for(int i=1;i<=n;i+=2) cout<<f[i].id<<' ';
    cout<<endl;
    for(int i=2;i<=n;i+=2) cout<<f[i].id<<' ';
    cout<<endl;
    return 0;
}


G - 判正誤

這題數據太水,就是 hash ,看後面數據怎麼加強 我的代碼是錯的
你們可以多取幾個模 增加正確率

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
struct node
{
    int a,b,id;
}f[N];
bool cmp(node a,node b)
{
    return a.a+a.b>b.a+b.b;
}
template<class T>
inline void read(T &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
LL qpow(LL a,LL p)
{
    LL res=1;
    while(p){
        if(p&1) res=res*a%mod;
        a=a*a%mod;
        p>>=1;
    }
    return res;
}
int main()
{
    int t;r(t);
    while(t--){
        LL a,b,c,d,e,f,g;
        rrr(a,c,e); rrr(b,d,f); r(g);
        if(qpow(a,b)+qpow(c,d)+qpow(e,f)==g) cout<<"Yes\n";
        else cout<<"No\n";
    }
    return 0;
}

H - 施魔法

居然真是DP,dp[ i ]表示的是 取前i個所消耗的最少魔力
轉移方程爲:dp[i]=min(dp[i-1]+f[i]-f[i-1],dp[i-m]+f[i]-f[i-m+1]);
可以這樣想,假如現在已經分了k段了,你要麼把下一個加入第k段,要麼讓這最後k個另成一段,取最小值.

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<string>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
using namespace std;
const int N=1e6+5;
const int M=2e3+5;
const int sz=17;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
typedef long long LL;
typedef pair<int,int> pt;
LL n,m;
int f[N];
int dp[N];
template<class T>
inline void read(T &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
int main()
{
    r(n); r(m);
    FOR(i,1,n) r(f[i]);
    sort(f+1,f+n+1);
    FOR(i,1,n) dp[i]=f[i]-f[1];
    FOR(i,2*m,n){
        dp[i]=min(dp[i-1]+f[i]-f[i-1],dp[i-m]+f[i]-f[i-m+1]);
    }
    cout<<dp[n]<<endl;
    return 0;
}


I - 建通道

我的寫法複雜了,因爲一開始題目看錯了 寫成這醜樣了,然後懶得改太多…
如果有相同的元素 那肯定讓他們之間連通 因爲花費爲0 把相同的去重掉就好了。 然後我們肯定是希望lowbit越小越好,我們就從最低爲開始往高位枚舉,設目前到了第k+1位 那如果這個元素&(1<<k) =1 把他放入一個集合A =0 放入一個集合 B 如果這兩個集合都不爲空 ,我們讓這兩個集合的元素互相連通就是讓所以元素連通了。 比如 A中有 a1 a2 ,B中有b1 b2 ,我們讓a1 連 b1 b2 ,a2連b1即可,一共花費即爲 (1<<k)*(n-1)

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
int f[N];
LL ans;
template<class T>
inline void read(T &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
void hhh(vector<int> v,LL st)
{
    vector<int> v1,v2;
    bool f1=0,f2=0;
    FOR(i,0,v.size()-1){
        if(v[i]&st){
            f1=1;
            v1.push_back(v[i]);
        }
        else{
            f2=1;
            v2.push_back(v[i]);
        }
    }
    if(f1&&f2){
        LL res=st*(v1.size()+v2.size()-1);
        ans=min(ans,res);
        return ;
    }
    if(f1) hhh(v1,st<<1);
    if(f2) hhh(v2,st<<1);
}
int main()
{
    r(n);
    FOR(i,1,n){
        r(f[i]);
    }
    sort(f+1,f+n+1);
    n=unique(f+1,f+n+1)-f-1;
    ans=0;
    if(n==0||n==1) cout<<ans<<endl;
    else{
        ans=INF;
        vector<int> v;
        FOR(i,1,n) v.push_back(f[i]);
        hhh(v,1);
        cout<<ans<<endl;
    }
    return 0;
}


J - 求函數

這題看出來了是線段樹 但是自己不知道改維護什麼
在這裏插入圖片描述
那就維護k的乘積和那個和就完事~

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<string>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
using namespace std;
const int N=1e6+5;
const int M=2e3+5;
const int sz=17;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1);
typedef long long LL;
typedef pair<LL,LL> pt;
LL n,m;
int kkk[N],ans1[N],ans2[N];
template<class T>
inline void read(T &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
void update(int k,int l,int r,int pos,int kk,int b)
{
    if(l==r){
        ans1[k]=kk;
        ans2[k]=b;
        return ;
    }
    int mid=(l+r)>>1;
    if(mid>=pos) update(ls,pos,kk,b);
    else update(rs,pos,kk,b);
    ans1[k]=1ll*ans1[k<<1]*ans1[k<<1|1]%mod;
    ans2[k]=(1ll*ans2[k<<1]*ans1[k<<1|1]+ans2[k<<1|1])%mod;
}
pt merge_pt(pt p1,pt p2)
{
    return mp(1ll*p1.first*p2.first%mod,(1ll*p1.second*p2.first%mod+p2.second)%mod);
}
pt query(int k,int l,int r,int x,int y)
{
    if(x<=l&&r<=y){
        return mp(ans1[k],ans2[k]);
    }
    int mid=(l+r)>>1;
    pt pp=mp(1,0);
    if(mid>=x) pp=merge_pt(pp,query(ls,x,y));
    if(mid<y) pp=merge_pt(pp,query(rs,x,y));
    return pp;
}
int main()
{
    r(n); r(m);
    FOR(i,1,n) r(kkk[i]);
    FOR(i,1,n){
        LL b;r(b);
        update(1,1,n,i,kkk[i],b);
    }
    while(m--){
        int op;
        r(op);
        if(op==1){
            int i,k,b;
            rrr(i,k,b);
            update(1,1,n,i,k,b);
        }
        else{
            int l,r;
            r(l); r(r);
            pt pp=query(1,1,n,l,r);
            //cout<<pp.first<<' '<<pp.second<<endl;
            cout<<(pp.first+pp.second)%mod<<endl;
        }
    }
    return 0;
}


下次加油哇~爭取多A個題

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章