Codeforces 868C Qualification Rounds - 位运算

Snark and Philip are preparing the problemset for the upcoming pre-qualification round for semi-quarter-finals. They have a bank of nproblems, and they want to select any non-empty subset of it as a problemset.

k experienced teams are participating in the contest. Some of these teams already know some of the problems. To make the contest interesting for them, each of the teams should know at most half of the selected problems.

Determine if Snark and Philip can make an interesting problemset!

Input

The first line contains two integers nk (1 ≤ n ≤ 105, 1 ≤ k ≤ 4) — the number of problems and the number of experienced teams.

Each of the next n lines contains k integers, each equal to 0 or 1. The j-th number in the i-th line is 1 if j-th team knows i-th problem and 0otherwise.

Output

Print "YES" (quotes for clarity), if it is possible to make an interesting problemset, and "NO" otherwise.

You can print each character either upper- or lowercase ("YeS" and "yes" are valid when the answer is "YES").

Examples
input
5 3
1 0 1
1 1 0
1 0 0
1 0 0
1 0 0
output
NO
input
3 2
1 0
1 1
0 1
output
YES
Note

In the first example you can't make any interesting problemset, because the first team knows all problems.

In the second example you can choose the first and the third problems.


  题目大意 有k个队参加比赛,有n道题目待选,是否可以选出一些题目使得每个队最多能做出选出的总题数

  在比赛的时候,根据人生的哲理和数学的直觉可以发现,其实能选出2个题目满足条件就行了。

  于是你把每个题目当成k位的二进制数,原题等价于选出两个数,使得它们and后的结果为0.

  这个可以把其中一个转化成补集,然后再枚举子集打flag,边读边打标记边判断,然后就完了。

  至于正确性的证明,只有1的队的时候显然,我就证一下只有2个队的情况

  已知选出了x(x > 3)个题目使得满足条件。求证其中存在两个题目就能满足条件

  1)当某一个是0 0,显然成立

  2)当某一个存在一个1,因为有不少于一半的那一位都是0,所以成立

  3)当某一个两位都是1,那么至多总共有x个1,除去这个至多有(x - 2)个1,但还剩下(x - 1)道题,根据鸽巢原理,一定存在一个是0 0.

  当存在3个队时,很多情况同理(不等式仍然满足,可以独立几列进行分析),当存在某一个3位都是1的时候,先考虑前两位,根据上面的情况3可以得到一定存在0 0 1或0 0 0,再考虑后两位,可以得到一定存在1 0 0或0 0 0,然后选出这个两个,完事。

  对于4个队的时候同理。

  (以上证明是自己证的,有问题请一定要指出)

Code

 1 /**
 2  * Codeforces
 3  * Problem#868C
 4  * Accepted
 5  * Time: 78ms
 6  * Memory: 0k
 7  */
 8 #include <bits/stdc++.h>
 9 using namespace std;
10 typedef bool boolean;
11 
12 int n, k;
13 
14 inline void init() {
15     scanf("%d%d", &n, &k); 
16 }
17 
18 boolean vis[20];
19 inline void solve() {
20     int rev_flag = (1 << k) - 1;
21     for(int i = 1, num, x; i <= n; i++) {
22         num = 0;
23         for(int j = 0; j < k; j++)
24             scanf("%d", &x), num <<= 1, num += x;
25         if(!num || vis[num]) {
26             puts("YES");
27             return; 
28         }
29         num ^= rev_flag;
30         for(int s = num; s; s = (s - 1) & num)
31             vis[s] = true;
32     }
33     puts("NO");
34 } 
35 
36 int main() {
37     init();
38     solve();
39     return 0;
40 }
posted @ 2017-10-06 20:20  阿波罗2003  阅读(370)  评论(0编辑  收藏  举报