C. Qualification Rounds(思维,特情)

C. Qualification Rounds

题意
给定 n * m 的 01 矩阵。
问,是否可以从中挑选出若干行,满足:

  • 对于每一列来说,挑选出的所有行中,1 的个数最多是总行数的一半。

1   ≤   n   ≤   1 0 5 , 1   ≤   k   ≤   4 1 ≤ n ≤ 10^5, 1 ≤ k ≤ 4 1 n 105,1 k 4

思路
也就是说,每一列 0 的个数要大于等于 1 的个数。

考虑特殊情况,最多只需要看两行。

如果发现存在一行全是 0,肯定满足。
如果发现存在两行,每一列至少有一个 0,那么也是满足的。

也就是找,是否存在两行,其对应位置相与之后,所有位置都为 0。也就是,将每一行转为二进制之后,是否存在两行相与为0。

n 最大为 10^5,但是 k 最大为 4,所以最多有 2^4 种行,二进制枚举 0到2^4,看哪些二进制出现过,二重循环暴力出现过的二进制看是否相与为 0。

Code

#include<bits/stdc++.h>
using namespace std;

#define Ios ios::sync_with_stdio(false),cin.tie(0)

const int N = 200010, mod = 1e9+7;
int T, n, m;
int a[N], f[N];

signed main(){
	Ios;
	cin >> n >> m;
	
	int flag = 0;
	
	for(int i=1;i<=n;i++)
	{
		int x = 0;
		for(int j=0;j<m;j++)
		{
			int t; cin >> t;
			if(t) x += 1<<j;
		}
		f[x] = 1;
		if(x == 0) flag = 1; //仅有一个都为0的行都满足,提前标记 
	}
	
	for(int i=0;i<1<<m;i++)
	{
		if(!f[i]) continue;
		for(int j=i+1;j<1<<m;j++)
		{
			if(!f[j]) continue;
			if((i & j) == 0) flag = 1; //注意 & 比 == 的优先级低,要加括号!! 
		}
	}
	if(flag) cout << "YES\n";
	else cout << "NO\n";
	
	return 0;
}

经验
一开始做的时候倒是想只拿两行的情况,但是也没手推一下,觉得不行就没再想。。
其实该画画的,如果画不出来别的情况那这样就是满足的,或者能直接证明最好。

所以有了思路一定要再想想,不要直接否定,也不要盲目肯定,先画画几个样例再说!说不定就是对的!!

还有就是要注意运算符优先级,注意 & 的优先级比 == 低,判断 i&j 是否为 0 是要加括号!
还有注意 i & (1<<j) 不一定是 0 或 1,而 i >> j & 1 的结果才是 0 或 1。
(i >> j & 1) == 0 这里也要加括号!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值