Two Choices(思维、奇偶性)

题目链接:http://icpc.upc.edu.cn/problem.php?cid=2874&pid=11


题目描述:
N N N students took a test with M M M questions with two choices: 0 0 0 and 1 1 1. You are given N strings of length M each: S 1 , S 2 , … , S N S_1,S_2,…,S_N S1,S2,,SN. The k-th character of S i S_i Si is 0 0 0 or 1 1 1, representing the response of the i-th student to the k-th question. Although we know the response of each student to each question, we do not yet know the correct answer ― 0 or 1 ― to each problem.
Find the number of pairs ( i , j ) (i,j) (i,j) satisfying 1 ≤ i < j ≤ N 1≤i<j≤N 1i<jN such that it is impossible for Student i i i and Student j j j to have the same number of correct answers.

Constraints
2 ≤ N ≤ 1 0 5 2≤N≤10^5 2N105
1 ≤ M ≤ 20 1≤M≤20 1M20
S i S_i Si is a string of length M M M consisting of 0 0 0 and 1 1 1.

输入
Input is given from Standard Input in the following format:

N M N M NM
S 1 S_1 S1
S 2 S_2 S2
:
S N S_N SN

输出
Print the answer.

样例输入
【样例1】
3 2
00
01
10
【样例2】
7 5
10101
00001
00110
11110
00100
11111
10000

样例输出
【样例1】
2
【样例2】
10

提示
样例1解释
For example, if the correct answers to the 1-st and 2-nd questions are both 0, Student 2 and Student 3 have the same number of correct answers ― 1. On the other hand, Student 1 and Student 2 never have the same number of correct answers, nor do Student 1 and Student 3.


大意:

n位同学,m个题目(答案为0或1),现有每个同学的每个题目的答案,但是没有正确答案。
问:一共有多少对同学,满足 不论正确答案为何,两位同学得分都不同。

思考:

看到 M ≤ 20 M≤20 M20,首先想到的就是 d f s dfs dfs。。但是遍历过所有答案之后,时间复杂度就 1 0 6 10^6 106了,最后连遍历n个同学的得分都不行。。然后就GG了。。

寻找规律:
不论正确答案为何,两个同学得分都不同。这样的两位同学的答案有一个特点:1的个数 一奇一偶!
如果两位同学得分相同的话,其答案中1的个数 都为奇数 或 都为偶数。

证明:
比如:

0 0 1 0 1 1 1
0 1 0 0 1 0 0 
  • 如果两个都是0 或者 两个都是1,那答案为0为1都可
  • 如果一个0一个1,那么如果为0,甲胜1,如果为1,乙胜1。
    如何能扳回来呢?在下一个01时刻。

所以为了得分相同,这样的01对一定是成对出现的!
也就是,两位同学答案中1的个数总和一定要为偶数。

这样的话,就要求甲同学答案中1的个数和乙同学答案中1的个数同奇偶!

那两位同学答案中1的个数一奇一偶时,得分一定不同。

于是这样的同学对数,就为 1的个数为奇数的同学数量 * 1个数为偶数的同学数量

实现:

计数答案中1的个数为奇数的同学数量,1的个数为偶数的同学数量。两者相乘就是一奇一偶的对数。

Code:

#include<iostream>
using namespace std;

const int N=200010;
int n,m,a[N];

int main(){
	cin>>n>>m;
	
	int cnt1=0,cnt2=0;
	for(int i=1;i<=n;i++)
	{
		int cnt=0;
		for(int j=1;j<=m;j++)
		{
			char c;cin>>c;
			if(c=='1') cnt++;
		}
		if(cnt%2) cnt1++;
		else cnt2++;
	 } 
	
	cout<<(ll)cnt1*cnt2;
	
	return 0;
}

确实,要想到这是道思维题,并且找出规律。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值