题目链接: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
1≤i<j≤N 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
2≤N≤105
1
≤
M
≤
20
1≤M≤20
1≤M≤20
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
M≤20,首先想到的就是
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;
}
确实,要想到这是道思维题,并且找出规律。。