试题 算法训练 审美课
问题描述
《审美的历程》课上有n位学生,帅老师展示了m幅画,其中有些是梵高的作品,另外的都出自五岁小朋友之手。老师请同学们分辨哪些画的作者是梵高,但是老师自己并没有答案,因为这些画看上去都像是小朋友画的……老师只想知道,有多少对同学给出的答案完全相反,这样他就可以用这个数据去揭穿披着皇帝新衣的抽象艺术了(支持帅老师_)。
答案完全相反是指对每一幅画的判断都相反。
输入格式
第一行两个数n和m,表示学生数和图画数;
接下来是一个n*m的01矩阵A:
如果aij=0,表示学生i觉得第j幅画是小朋友画的;
如果aij=1,表示学生i觉得第j幅画是梵高画的。
输出格式
输出一个数ans:表示有多少对同学的答案完全相反。
样例输入
3 2
1 0
0 1
1 0
样例输出
2
样例说明
同学1和同学2的答案完全相反;
同学2和同学3的答案完全相反;
所以答案是2。
数据规模和约定
对于50%的数据:n<=1000;
对于80%的数据:n<=10000;
对于100%的数据:n<=50000,m<=20。
思路如下
- 在存的时候,存入数组的是二进制,这里用到了移位运算符“<<”
- 将该二进制表示的整数值作为新的数组索引,来表示不同小朋友判断完全一样的次数(用map、int数组都行, 此处的数组为res[] )
- 用异或运算遍历每一个小朋友的结果,对每一个二进制串按位取反后索引,找到与该小朋友完全相反的个数加到ans中
- 用max = (1 << m) - 1; //构造全1二进制数
- 最后ans/2是因为重复计算,除以2之后才是“有多少对同学”。
关于左移运算符<<的使用
代码如下
#include <stdio.h>
int A[50005];
int res[20000000] = {0};
int ans = 0;
int main()
{int n, m; //n个学生, m幅画 int i, j;int tmp;scanf("%d%d", &n, &m);for(i=0; i<n; i++){for(j=0; j<m; j++){scanf("%d", &tmp);A[i] = (A[i]<<1) + tmp; //关键就是这个"左移运算符" }res[A[i]]++;}int max = (1 << m) - 1; //构造全1二进制数for(i=0; i<n; i++) {tmp = A[i] ^ max; //用异或运算进行按位取反ans = ans + res[tmp] ;}printf("%d\n", ans/2);return 0;
}