[高斯消元]UVA 12961 Lottery

题目链接:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4840



The lottery BWS is played annually. In this lottery N people bet choosing K numbers each. In aformal way, we can say that Bij is the j-th value bet by the i-th person. Then the organizers chooseK positive integers. The chosen numbers are called W1, W2, . . . , WK.

The winners are calculated as followed:

• A non-empty subset is chosen randomly from the N participants; in other words, some participantsare luckily chosen.

• For each person in this subset the value S1 is calculated, the sum of all the first numbers bet bythem, that is, the sum of the Bi1 where i is the index of each chosen person. In the same waythe values S2, . . . , SK are calculated.

• A parity test between Wj and Sj is performed; in other words, it is verified if the parity (if anumber is pair or odd) matches between W1 and S1, W2 and S2, and so on until WK and SK.

• If all parities match, then the people in this subset are considered the winners!The organizers want to know: is it possible to pick the numbers W1, W2, . . . , WK so that there is nosubset of winning participants?

Input

The input contains several test cases. The first line of a test case contains the numbers N (1 ≤N ≤ 30000) and K (3 ≤ K ≤ 50), which represent the number of participants and the quantity ofnumbers bet by each person, respectively. The participants bet with integer numbers between 1 and109, inclusive. Each of the next N lines contains K numbers representing the bet of each person, oneperson per line.

Output

For each test case in the input you must output a single line, containing one letter: ‘S’ in case it ispossible or ‘N’ otherwise.

Sample Input

2 3

1 2 3

5 6 7

3 3

3 2 1

6 5 4

4 4 4

4 3

9 4 7

4 4 4

2 7 2

2 2 1

Sample Output

S

S

N

---------------------------------------------------------分割线------------------------------------------------------------

这个题目说,选择任意x行相加,共有2^N-1种可能,问是否存在一个序列。和所有的可能,至少存一个数,然后他们奇偶不同。

其实我们可以这么想,我们把加起来的数都对2取余,这样的话偶数就为0,奇数为1,这样我们就可以把每一行看成一个数了,那么不符合的条件无论我们怎么写,都存在一个数和我们写的数是一样的。

由于我们的写法有2^k种可能,所以对于N<=k的,我们绝对能写出一个数和不等于其中的任意的数。


下面我们讨论关于k<N的情况:

然后我们再考虑一个东西:奇+奇=偶数,奇+偶=奇,偶+偶=偶。这个是个很好的性质。它和异或是一样的。

所以把相加变成异或,这个有什么用呢?其实是因为异或的一个性质,x^x=0。也就是说,我们通过多步异或之后,可以换成0次或者1次,也就是取或者不取。

然后我们就可以用矩阵了。为什么用矩阵?其实是这样的。假设我前k行能够搞出一个上三角阵或者单位阵的话,那么我上面异或就可以得到1到2^k-1所有数,而我们现在是k<N。也就是说除却k行之外,还有其他的行,用其中任意一个和上面的若干个异或,又可以得到0,也就是说2^k种可能都可以表示出来。

-------------------------------------------------分割线-------------------------------------------------------------------

总结:

对于k>=N的情况,直接就是S;

对于k<N的情况,高斯消元之后看看前k行对角线是否都为1,如果是的话,那么就是N,否则就是S。

#include<cstdio>
#include<algorithm>
using namespace std;

int num[40000][60];
bool Guss(int n,int r)
{

	if(r>=n)
		return false;
	for(int i=0; i<r; i++) {
		for(int j=i; j<n; j++) {
			if(num[j][i]) {
				for(int k=0; k<r; k++)
					swap(num[i][k],num[j][k]);
				break;
			}
		}
		for(int j=i+1; j<n; j++) {
			if(num[j][i])
				for(int k=0; k<r; k++) {
					num[j][k]^=num[i][k];
				}
		}
	}
	int xx=min(n,r);
	for(int i=0; i<xx; i++)
		if(!num[i][i])
			return false;
	return true;
}

int main()
{
	int n,k;
	while(scanf("%d%d",&n,&k)!=EOF) {
		for(int i=0; i<n; i++) {
			for(int j=0; j<k; j++) {
				scanf("%d",&num[i][j]);
				num[i][j]&=1;
			}
		}
		int x=Guss(n,k);
		if(x)
			printf("N\n");
		else
			printf("S\n");
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值