zoukankan      html  css  js  c++  java
  • 套题 codeforces 360

    A题:Opponents

    直接模拟

    #include <bits/stdc++.h>
    using namespace std;
    char ch[200];
    int main()
    {
        int n,k;
        while(~scanf("%d%d",&n,&k))
        {
            int p=0,sta=1,first=1,ans;
            for(int i=0;i<k;i++)
            {
                sta=1;
                scanf("%s",ch);
                for(int i=0;i<n;i++) sta&=(ch[i]-'0');
                if(sta==0) p++;
                if(sta==1||(i==k-1))
                {
                    if(first) {ans=p;first=0;}
                    else
                    {
                        ans=max(ans,p);
                    }
                    p=0;
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    B题: Lovely Palindromes
    偶数长度的回文串
    可以把这个回文串当做两半来处理,对于任何一个数字,只要把它反转后加到
    数字尾,就可以形成一个回文串,且符合偶数长度的条件
    既然任何数字都可以,那么第n个数就是以n来构造的

    #include <bits/stdc++.h>
    using namespace std;
    const int Max=1e5+10;
    char ch[Max];
    int main()
    {
        while(~scanf("%s",ch))
        {
            printf("%s",ch);
            reverse(ch,ch+strlen(ch));
            printf("%s
    ",ch);
        }
        return 0;
    }
    View Code

    C题:NP-Hard Problem
    要求将一张图分成两个顶点集合,每个集合包含所有的边
    要使得这样的集合成立,必须把每一条边上的两点分别分到两个集合中去
    可以利用并查集分点,一个集合祖先节点小于等于n(小于等于(因为n+n))
    另一个祖先节点大于n。
    这两个集合有没有交集取决于同一条边上的两个顶点不能在同一集合

    #include <bits/stdc++.h>
    using namespace std;
    const int Max=1e5+10;
    int fa[Max*2];
    int find(int x)
    {
        return fa[x]==-1?x:fa[x]=find(fa[x]);
    }
    void Union(int x,int y)
    {
        int f1=find(x),f2=find(y);
        if(f1!=f2) fa[f1]=f2;
    }
    vector<int>ans1,ans2;
    int vis[Max];
    int main()
    {
        int n,m;
        while(~scanf("%d%d",&n,&m))
        {
            memset(fa,-1,sizeof(fa));
            memset(vis,0,sizeof(vis));
            int u,v,flag=0;
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d",&u,&v);
                if(find(u)==find(v)) flag=1;  //两个顶点已经在同一集合,无解
                Union(u,v+n);
                Union(u+n,v);
                vis[u]=vis[v]=1;
            }
            ans1.clear();ans2.clear();
            for(int i=1;i<=n;i++)
            {
                if(!vis[i]) continue;
                if(find(i)<=n) ans1.push_back(i);
                else ans2.push_back(i);
            }
            if(ans1.empty()||ans2.empty()||flag) puts("-1");
            else
            {
                if(ans1.size()>ans2.size()) swap(ans1,ans2);
                printf("%d
    ",ans1.size());
                for(int i=0;i<ans1.size();i++)
                {
                    if(i) printf(" ");
                    printf("%d",ans1[i]);
                }
                printf("
    %d
    ",ans2.size());
                for(int i=0;i<ans2.size();i++)
                {
                    if(i) printf(" ");
                    printf("%d",ans2[i]);
                }
                puts("");
            }
        }
        return 0;
    }
    View Code

    同样地,既然已经知道了解这道题的关键就是让每一条边的两个点分散到
    两个不同的集合里面,那么直接dfs进行染色也是一个简洁易写的方法

    #include <bits/stdc++.h>
    using namespace std;
    const int Max=1e5+10;
    vector<int>G[Max];
    vector<int>ans1,ans2;
    int vis[Max],col[Max];
    bool dfs(int u,int c,int pre)
    {
        col[u]=c;
        int v;
        for(int i=0;i<G[u].size();i++)
        {
            v=G[u][i];
            if(v==pre) continue;
            if(col[v]==c)  return 0;
            if(col[v]!=-1) continue;
            if(!dfs(v,!c,u)) return 0;
        }
        return 1;
    }
    int main()
    {
        int n,m;
        while(~scanf("%d%d",&n,&m))
        {
            memset(vis,0,sizeof(vis));
            memset(col,-1,sizeof(col));
            int u,v;
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d",&u,&v);
                G[u].push_back(v);
                G[v].push_back(u);
                vis[u]=vis[v]=1;
            }
            int root,flag=0;
            for(int i=1;i<=n;i++) if(vis[i])
            {
                root=i;
                if(col[root]!=-1) continue;
                if(!dfs(root,1,0)) flag=1;
            }
            if(flag) puts("-1");
            else
            {
                ans1.clear();ans2.clear();
                for(int i=1;i<=n;i++)
                {
                    if(col[i]==1) ans1.push_back(i);
                    if(col[i]==0) ans2.push_back(i);
                }
                if(ans1.size()>ans2.size()) swap(ans1,ans2);
                printf("%d
    ",ans1.size());
                for(int i=0;i<ans1.size();i++)
                {
                    if(i) printf(" ");
                    printf("%d",ans1[i]);
                }
                printf("
    %d
    ",ans2.size());
                for(int i=0;i<ans2.size();i++)
                {
                    if(i) printf(" ");
                    printf("%d",ans2[i]);
                }
                puts("");
            }
        }
        return 0;
    }
    View Code

    D题:Remainders Game
    已知:
    x mod c1 = m1
    x mod c2 = m2
    ......
    x mod cn = mn
    这里要求知道x mod (k)的值,那么就要求lcm(c1,c2,c3,.....,cn)==k,并且ci之间互质

    #include <bits/stdc++.h>
    #define scan(x,y) scanf("%d%d",&x,&y)
    using namespace std;
    typedef long long LL;
    const int Max=1e5+10;
    int n,m;
    LL gcd(LL a,LL b)
    {
        return b==0?a:gcd(b,a%b);
    }
    int main()
    {
        scan(n,m);
        LL ans=1;
        int x;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            ans=gcd((LL)m,ans*(LL)x/gcd(ans,x));
        }
        if(ans==(LL)m) cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
        return 0;
    }
    View Code

    E题:The Values You Can Make
    有n个价值不一的硬币,问能够凑出的所有面值(<=m)
    dp[i][j],意为已经拥有j面值的情况下,能否凑成j面值
    1.dp[0][0]=1
    2.if(dp[l-x][j]) dp[l][j]=1 and dp[l][j+x]=1;
    3.已拥有的硬币转移方向应该从大到小,因为用一枚硬币不能使用多次,不能对后面的
    数值持续影响

    #include <bits/stdc++.h>
    using namespace std;
    const int Max=500+10;
    short dp[Max][Max];
    vector<int>ans;
    int main()
    {
        int n,k;
        while(~scanf("%d%d",&n,&k))
        {
            memset(dp,0,sizeof(dp));
            dp[0][0]=1;
            int x;
            for(int i=0;i<n;i++)
            {
                scanf("%d",&x);
                for(int l=k;l>=x;l--)
                {
                    for(int r=0;r<=k-x;r++)
                    {
                        if(dp[l-x][r]) dp[l][r]=dp[l][r+x]=1;
                    }
                }
            }
            ans.clear();
            for(int i=0;i<=k;i++)
            {
                if(dp[k][i]) ans.push_back(i);
            }
            printf("%d
    ",ans.size());
            for(int i=0;i<ans.size();i++)
            {
                if(i) printf(" ");
                printf("%d",ans[i]);
            }
            puts("");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    代码管理模型概况
    循环链表
    队列

    链表
    java 2020-10-12T11:22:49.000+0800 字符串转换成正常时间格式
    动态数组
    mysql练习
    复杂度与LeetCode
    记一次带逗号的数字类型处理
  • 原文地址:https://www.cnblogs.com/zsyacm666666/p/5738007.html
Copyright © 2011-2022 走看看