Codeforces Round #360 (Div. 2) C D E

Posted 天翎月

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #360 (Div. 2) C D E相关的知识,希望对你有一定的参考价值。

每次AB秒出 到了C难度陡然上升...翻译都弄不懂...

C 给出一张图 找出两个点的覆盖集(覆盖集是指这图中每条边都有至少一个点在这个点集里面) 并且两个点集没有交集 英文很难看懂...就是二分图的判定 看看这张图是不是二分图 输出两边的点 不是二分图输出-1

坑点是这是special judge 但是题目没说 每个联通块都要进行一次bfs 那些独立点可以不输出也可以随意分配

D 给出k与n个数ci 我们知道一个未知的数x%ci的数 问能不能求出x%k的数

可以利用中国剩余定理来解 

如果我们知道 x=A mod c1 = B mod c2 可以求出x的通解  x= lcm(c1,c2)q+z 这里的q是一个倍数

那么当lcm(c1,c2...)是k的倍数的时候 满足 所有的 kq都有lcm()q来对应 所以这时候一定可以通过z求出x%k 

所以只需要求一下ci之间的lcm就好啦 最后看lcm是不是k的倍数

但是 直接求lcm会超int什么的 

可以每次都让lcm%=k 一旦lcm为k的倍数的时候就永远为0下去了

E A有n个硬币 B有k价值的东西 A从这些硬币中找出一些使和等于k和B交换 A想知道B能利用这些硬币摆出多少的状态 都输出

设置dp[i][j] i表示A拿出的硬币的总和 j表示从这些硬币中拿出来的部分的总和 1 为存在 0 为不存在

初始dp[0][0]=1

关于代码内dp方程的转移:首先枚举硬币的种类 再枚举i 需要注意的是i要从大往小去枚举 这和背包中01和完全的区别类似 当我们从上向下枚举的时候 就不会出现同一种东西加成在小东西上 又在小东西升级的大东西上再次作用这种状况了 问题中硬币是只有一个的 所以是01 从上向下枚举 而当面对完全背包的情况下 我们可以无限制的加入东西 所以应该从小往下枚举 枚举j的时候只需要从0向k枚举就好 因为之后还会进行判断 dp[i][j]==1 这时候就说明这种状态是存在的 然后我们对dp[i+c][j]和dp[i+c][j+c]进行操作 可以看出 由于枚举硬币的顺序 每个状态的i和j都只能被放进去一种硬币 

初始化的时候只做dp[0][0]就好 其余的让它自己去推...

C

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<math.h>
#include<iostream>
#include<queue>
using namespace std;
int n,m;
int point[100050];
struct node
{
    int v;
    int nex;
};
node b[200050];
int cnt;
void add(int u,int v)
{
    b[cnt].v=v;
    b[cnt].nex=point[u];
    point[u]=cnt;
    cnt++;
}
int co[100050];
bool bfs(int z)
{
    queue<int >q;
    q.push(z);
    co[z]=1;
    while(!q.empty())
    {
        int f=q.front();
        q.pop();
        for(int tt=point[f]; tt!=-1; tt=b[tt].nex)
        {
            int v=b[tt].v;
            if(co[v]==0)
            {
                if(co[f]==1)
                {
                    co[v]=2;
                    q.push(v);
                }
                else
                {
                    co[v]=1;
                    q.push(v);
                }
            }
            else if(co[v]==co[f])
            {
                return false;
            }
            else
            {
                continue;
            }
        }
    }
    return true;
}

int main()
{
    cin>>n>>m;
    cnt=0;
    for(int i=1; i<=n; i++)
    {
        point[i]=-1;
        co[i]=0;
    }
    for(int i=1; i<=m; i++)
    {
        int u,v;
        cin>>u>>v;
        add(u,v);
        add(v,u);
    }
    bool ans=true;
    for(int i=1;i<=n;i++){
        if(co[i]==0){
            ans=bfs(i);
            if(ans==false){
                printf("-1\n");
                break;
            }
        }
    }
    if(ans==true){
        int res=0;
        for(int i=1; i<=n; i++)
        {
            if(co[i]==1)
            {
                res++;
            }
        }
        printf("%d\n",res);
        int c=0;
        for(int i=1; i<=n; i++)
        {
            if(co[i]==1)
            {
                printf("%d",i);
                c++;
                if(c==res)
                    printf("\n");
                else printf(" ");
            }
        }
        c=0;
        res=0;
        for(int i=1; i<=n; i++)
        {
            if(co[i]!=1)
            {
                res++;
            }
        }
        printf("%d\n",res);
        for(int i=1; i<=n; i++)
        {
            if(co[i]!=1)
            {
                printf("%d",i);
                c++;
                if(c==res)
                    printf("\n");
                else printf(" ");
            }
        }
    }
}

D

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
#include<iostream>
using namespace std;
long long k;
int n;
long long gcd(long long a,long long b)
{
    if(b==0)
        return a;
    return gcd(b,a%b);
}
long long lcm(long long a, long long b)
{
    return a*b/gcd(a,b);
}
int main()
{
    scanf("%d%lld",&n,&k);
    long long cc;
    scanf("%lld",&cc);
    long long gbs=cc;
    bool ans=false;
    if(k==1)
    {
        ans=true;
    }
    if(n==1)
    {
        if(cc%k==0)
            ans=true;
    }
    for(int i=2; i<=n; i++)
    {
        scanf("%lld",&cc);
        if(ans==true)
            continue;
        gbs=lcm(cc,gbs);
        gbs%=k;
        if(gbs==0)
        {
            ans=true;
        }
    }
    if(ans==true)
    {
        printf("Yes\n");
    }
    else printf("No\n");
}

E

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
using namespace std;
int n,k;
int c[505];
int dp[500][500];
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1; i<=n; i++)
        scanf("%d",&c[i]);
    memset(dp,0,sizeof(dp));
    /*for(int i=1; i<=n; i++)
    {
        dp[c[i]][c[i]]=dp[c[i]][0]=1;
    }*/
    dp[0][0]=1;
    for(int i=1; i<=n; i++)
    {
        for(int j=k-c[i]; j>=0; j--)
        {
            for(int o=0; o<=k; o++)
            {
                if(dp[j][o]==1)
                {
                    dp[j+c[i]][o]=1;
                    if(o+c[i]<=k)
                    {
                        dp[j+c[i]][o+c[i]]=1;
                    }
                }
            }
        }
    }
    int ans=0;
    for(int i=0; i<=k; i++)
    {
        if(dp[k][i]==1)
        {
            ans++;
        }
    }
    printf("%d\n",ans);
    int s=0;
    for(int i=0; i<=k; i++)
    {
        if(dp[k][i]==1)
        {
            {
                printf("%d",i);
                s++;
                if(s==ans)
                    printf("\n");
                else printf(" ");
            }
        }
    }
}

拖了两天才补完的cf..补题的感觉真是亦可赛艇...

以上是关于Codeforces Round #360 (Div. 2) C D E的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #360 C

Codeforces Round #360 D

Codeforces Round #360 E

Codeforces Round #360 (Div. 2) D 数学推导 E dp

Codeforces Round #360 (Div. 1) D. Dividing Kingdom II 并查集求奇偶元环

Codeforces Round #360 (Div. 2) C D E