zoukankan      html  css  js  c++  java
  • Codeforces Round #554 (Div. 2)自闭记

    A

    签到

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,s[2],t[2],ans;
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1,x;i<=n;i++)scanf("%d",&x),s[x&1]++;
        for(int i=1,x;i<=m;i++)scanf("%d",&x),t[x&1]++;
        ans=min(s[0],t[1])+min(s[1],t[0]);
        printf("%d",ans);
    }
    View Code

    B

    要求40次,而log(1e6)≈20,也就是说最多20个二进制位,可以每次翻转最高的“0”位,然后再+1即可。证明:若为11...10...00,则翻转最高0位后直接结束;若为全1,也是直接结束;若后面存在1,翻转后必然存在0,使得最高位向后走。

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,tim,a[1000];
    bool judge(int x)
    {
        int flag=1;
        for(int i=30;i>=0;i--)
        if(x&(1<<i))flag=0;
        else if(!flag)return 0;
        return 1;
    }
    int main()
    {
        cin>>n;
        while(!judge(n))
        {
            tim++;
            if(tim&1)
            {
                int flag=1;
                for(int i=30;i>=0;i--)if(n&(1<<i))flag=0;else if(!flag){a[++m]=i+1;break;}
                n^=(1<<a[m]+1)-1;
            }
            else n++;
        }
        printf("%d
    ",tim);
        for(int i=1;i<=m;i++)printf("%d ",a[i]);
    }
    View Code

    C

    签到,开始还看成了最大公约数,自闭。其实就是枚举差值的每个因数,暴力加一下即可。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll a,b,d,ans,mn;
    void work(ll x)
    {
        ll t=(x-a%x)%x,A=a+t,B=b+t,g=A/__gcd(A,B)*B;
        if(g<mn)mn=g,ans=t;
        else if(g==mn&&t<ans)ans=t;
    }
    int main()
    {
        cin>>a>>b;
        if(a==b){cout<<0;return 0;}
        if(a>b)d=a-b;else d=b-a;
        mn=a/__gcd(a,b)*b;
        for(ll i=1;i*i<=d;i++)
        if(d%i==0)work(i),work(d/i);
        cout<<ans;
    }
    View Code

    D

    被这题搞自闭了,看到什么最大值对1e9+7取模以为是个神仙题,后来才发现是个SB贪心题,其实就是能选的边尽量选,后来证明了一下:只有一个儿子显然,有两个儿子可以证明:如果自己能选没选,那么两个儿子的边也只能选1个,还会影响后面,如果自己不能选,随机选一个是也是对的。然后可以f[i][j][0/1]表示走了i步,前缀和为j,该点与父亲的边是否被选的节点数有几个,直接暴力转移即可。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1007,mod=1e9+7;
    int n,ans,f[2*N][N][2];
    void add(int&x,int y){x=(x+y)%mod;}
    int main()
    {
        scanf("%d",&n);
        f[1][1][1]=1;
        for(int i=1;i<=2*n;i++)
        for(int j=0;j<=n;j++)
        {
            int lc=n+1,rc=n+1;
            if(j+1<=2*n-i-1)lc=j+1;
            if(j)rc=j-1;
            if(lc>n&&rc>n)continue;
            if(f[i][j][0])
            {
                if(lc<=n&&rc<=n)add(f[i+1][lc][1],f[i][j][0]),add(f[i+1][rc][0],f[i][j][0]);
                else if(lc<=n)add(f[i+1][lc][1],f[i][j][0]);
                else add(f[i+1][rc][1],f[i][j][0]);
            }
            if(f[i][j][1])
            {
                if(lc<=n)add(f[i+1][lc][0],f[i][j][1]);
                if(rc<=n)add(f[i+1][rc][0],f[i][j][1]);
            }
        }
        for(int i=1;i<=2*n;i++)
        for(int j=0;j<=n;j++)
        if(f[i][j][1])add(ans,f[i][j][1]);
        printf("%d",ans);
    }
    View Code

    E

    被D搞自闭了,E也不会了。其实这道题有一种很神奇的做法:首先当然把b[i]>c[i]的判掉,然后不难发现相邻2个值中一定一个是最大值,另一个是最小值,然后连接(n-1)条(b[i],c[i])的无向边,然后跑一遍欧拉路,若存在长度为n的欧拉路就可以输出解了。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e5+7;
    int n,m,cnt,tot,a[N],b[N],c[N],w[N],hd[N],v[N<<1],nxt[N<<1],vis[N],du[N];
    map<int,int>id;
    void add(int x,int y)
    {
        v[++cnt]=y,nxt[cnt]=hd[x],hd[x]=cnt,du[x]++;
        v[++cnt]=x,nxt[cnt]=hd[y],hd[y]=cnt,du[y]++;
    }
    int getid(int x)
    {
        if(!id[x])w[id[x]=++tot]=x;
        return id[x];
    }
    void euler(int u)
    {
        for(int &i=hd[u];i;i=nxt[i])
        if(!vis[i>>1])vis[i>>1]=1,euler(v[i]);
        a[++m]=u;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<n;i++)scanf("%d",&b[i]);
        for(int i=1;i<n;i++)scanf("%d",&c[i]);
        cnt=1;
        for(int i=1;i<n;i++)
        if(b[i]>c[i]){puts("-1");return 0;}
        else add(getid(b[i]),getid(c[i]));
        int S=1,num=0;
        for(int i=1;i<=tot;i++)if(du[i]&1)S=i,num++;
        if(num&&num!=2){puts("-1");return 0;}
        euler(S);
        if(m!=n){puts("-1");return 0;}
        for(int i=1;i<=n;i++)printf("%d ",w[a[i]]);
    }
    View Code

    F

    神仙题,看某AC代码写了F1,大概是f[i][j][k]表示长为i,走j步,后面覆盖集合为k的方案数,直接根据题意转移状态。后来发现F2也没意思就是一样的做法,加个矩阵快速幂就行了,不过懒得写了。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+7,mod=1e9+7;
    int n,k,m,ans,sz[25],f[N][13][16];
    int main()
    {
        scanf("%d%d%d",&n,&k,&m);
        for(int i=1;i<1<<m;i++)sz[i]=sz[i>>1]+(i&1);
        f[1][1][1]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<k;j++)
            for(int S=0;S<1<<m;S++)
            if(f[i][j][S])
            {
                int nS=((S<<1)&((1<<m)-1));
                f[i+1][j][nS]=(f[i+1][j][nS]+f[i][j][S])%mod;
                f[i+1][j+1][nS|1]=(f[i+1][j+1][nS|1]+1ll*f[i][j][S]*(sz[S]+1))%mod;
            }
            int sum=0;
            for(int S=0;S<(1<<m);S++)sum=(sum+f[i][k][S])%mod;
            ans=(ans+1ll*sum*(n-i+1))%mod;
        }
        printf("%d",ans);
    }
    View Code

    新号打的,初始语言默认C差评,被卡了十几分钟CE不知道,十分不爽。

    result:rank95 rating+=225 now_rating=1725

  • 相关阅读:
    LeNet && ModernCNN
    Fundamentals of Convolutional Neural Networks
    机器及其相关技术介绍
    学而后思,方能发展;思而立行,终将卓越
    贪心的区间问题
    基环树
    模板类
    存储问题
    大佬们的技巧
    exgcd
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/10766200.html
Copyright © 2011-2022 走看看