Codeforces868C. Qualification Rounds

Posted ONION_CYC

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces868C. Qualification Rounds相关的知识,希望对你有一定的参考价值。

【题目】C. Qualification Rounds

【题意】给定n个问题和K个人,给定每个人知道的问题列表,求能否找到一个非空问题集合,满足每个人知道的集合中问题数量都不超过集合总题数的一半。n<=10^5,k<=4。

【算法】数学结论

【题解】当k<=4时,结论:若存在合法方案,则一定存在选择2个问题的合法方案

证明:对于选择偶数个问题的合法方案(奇数不优),假设方案中每个人都知道一半问题(最坏),试图从中得到选择2个问题的合法方案。

先得到三条易证的结论:

Ⅰ两个人知道区间互补,则找不到问题满足这两个人都不知道。

Ⅱ否则,至少存在一个问题满足这两个人都不知道。

Ⅲ多个人知道区间一致,则至少存在一个问题满足这多个人都不知道。

①若不存在Ⅰ,则把4个人分成2组,每组内由Ⅱ可得1个问题。如果2个问题一致说明这两人对应那两人区间分别一致,由Ⅲ可知交换搭档即可。

②若存在Ⅰ,则把互补分到不同组。若一个人和另外三个人都互补,另外三个人由Ⅲ得到1个问题,一个人再得到1个问题。

得证。

技术分享
#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
int read(){
    char c;int s=0,t=1;
    while(!isdigit(c=getchar()))if(c==-)t=-1;
    do{s=s*10+c-0;}while(isdigit(c=getchar()));
    return s*t;
}
/*------------------------------------------------------------*/
const int inf=0x3f3f3f3f;

int n,kind,a[100010];
bool c[10000];

int main(){
    n=read();kind=read();
    for(int i=1;i<=n;i++){
        for(int j=1;j<=kind;j++)a[i]=(a[i]<<1)+read();
        c[a[i]]=1;
    }
    if(c[0]){printf("YES");return 0;}
    for(int i=1;i<(1<<kind);i++)if(c[i]){
        int x=i^((1<<kind)-1);
        for(int j=1;j<(1<<kind);j++)if(c[j]&&(x&j)==j){printf("YES");return 0;}
    }
    printf("NO");
    return 0;
}
View Code

 

以上是关于Codeforces868C. Qualification Rounds的主要内容,如果未能解决你的问题,请参考以下文章

[Codeforces Round #438][Codeforces 868C. Qualification Rounds]

Codeforces868C. Qualification Rounds

Codeforces-868C. Qualification Rounds(状压)

codeforces 868C - Qualification Rounds(构造)

F - Qualification Rounds CodeForces - 868C 二进制

[Codeforces Round #438][Codeforces 868D. Huge Strings]