1. 程式人生 > >[Codeforces Round #438][Codeforces 868C. Qualification Rounds]

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

span return 集合 lose main 情況 view ace 否則

題目鏈接:868C - Qualification Rounds

題目大意:有\(n\)個題目,\(k\)個人,每個人可能做過這\(n\)個題裏的若幹道,出題方要在這\(n\)個題目裏選若幹個出來作為一套題。稱一套題有趣的當且僅當對於任意一個人,他在這套題裏做過的題目數不超過總題數的一半,問是否存在這樣的一套題。

題解:設第\(i\)道題有\(p_i\)個人做過,顯然當存在有\(p_i =0\)時單獨把這道題放入套題裏即可。

   若存在\(p_i =1\),設做過這道題的人為\(X\),則只需要找到一道題\(j\),使得\(X\)沒做過這道題,這時只要出\(i,j\)這兩道題就好了。若沒有找到這樣的題,則說明\(X\)做過全部的題,必然無解。

   當排除了以上情況後,可以發現有\(p_i\geqslant 2\)恒成立,因此若設套題中的題目個數為\(x\),則有\(\sum p_i\geqslant 2x\)。如果存在一套有趣的題,則對這套題一定有\(\sum p_i\leqslant \frac{kx}{2}\)(每個人最多知道\(\frac{x}{2}\)道題,一共\(k\)個人)。所以在這種情況下,若\(k<4\)則無解,否則一定有\(\sum p_i = 2x\),即\(p_i =2\)。找出兩道知道的人不重復的題就好了,否則的話由於任意兩道題都會有相同的人知道,一定會導致無解。用二進制的形式記錄每道題有哪幾個人知道,放入集合中查找就好了。

技術分享圖片
#include<bits/stdc++.h>
using namespace std;
#define N 100001
int n,k,a,b,f[N][5],p[N],w[N];
set<int>s;
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
      {
      for(int j=1;j<=k;j++)
        scanf("%d",&f[i][j]),
        w[i]^=f[i][j]<<(j-1),
        p[i]
+=f[i][j]; if(p[i]==0)return printf("YES\n"),0; s.insert(w[i]); } for(int j=0;j<k;j++) { a=b=0; for(int i=1;i<=n;i++) { if(p[i]==1 && w[i]==1<<j)a=1; if(!(w[i]&(1<<j)))b=1; } if(a)return printf("%s\n",b?"YES":"NO"),0; } for(auto i:s)if(s.count(15-i))return printf("YES\n"),0; return printf("NO\n"),0; }
View Code

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