问题描述
《审美的历程》课上有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。
本来看着这个提很简单用了三重循环判断就ok了,但是提交上去之后发现只是通过了一半,其余都是时间超时,看来测试数据是非常大的…又去网上找别人的代码。。。。这位大佬的博客~戳戳戳进去----
当然是讲解它的代码。。。
大体的思路是 :
如果两个同学的判断完全相反,那么他们异或之后为全1
例如 011 ^ 100 = 111
我们利用全1 ^ 011 = 100,只要在列表里面查找是否存在100就可以判断有没有完全相反。
所以
**import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.HashMap;
import java.util.Map.Entry;**
public class Main {
**private static Reader reader;
public static void main(String[] args) {
reader = new InputStreamReader(System.in);
int n, m;
n = getInt();
m = getInt();
HashMap<Integer, Integer> hm = new HashMap<>(n);**
**111、for (int i = 0; i < n; ++i) {
int num = 0, x = 0;
for (int j = 0; j < m; j++) {
x = getInt();
num = (num << 1) + x;//对于读取进来的二进制转换为十进制的数字
//num<<1 表示将二进制的数字向左移动一位
例如:
3 = 011
第一次读取 0 (num<<1)->00 + 0 =>00 num = 0
第二次读取 0 (num<<1)->00 + 1 =>01 num = 1
第三次读取 1 (num<<1)->10 + 1 =>11 num = 3
}
hm.put(num, hm.containsKey(num) ? hm.get(num) + 1 : 1);
这个地方是判断是否已经这个答案,如果没有,就将人数变成1;
如果说已经有同学是这个答案,那么将人数继续加一。
}**
222、 **int sum = 0, maxn = (1 << m) - 1;
for (Entry<Integer, Integer> entry : hm.entrySet()) {
if (maxn / 2 < entry.getKey())
continue;
int key = entry.getKey() ^ maxn;
if (hm.containsKey(key))
sum += hm.get(key) * entry.getValue();
}
System.out.println(sum);
# //拿到一个同学的答案key,取异或之后查找列表里是否有这个答案
# //hm.get(key) * entry.getValue(); 举个栗子:如果有2个人是011 三个人 是 100,那么完全相反的组合共有2*3 = 6对。
}**
333、 **public static int getInt() {
int res = 0, read;
try {
while ((read = reader.read()) != -1) {
if (Character.isDigit(read)) {// 因为全是非负数,不需要判断负号‘-’,只要是数字就行
res = read - '0';
while ((read = reader.read()) != -1) {// 继续得到能得到的数字
if (Character.isDigit(read)) {
res = res * 10 + (read - '0');
} else {
break;
}
}
break;
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return res;
}**
## getInt方法是在提取的字符流reader中逐个判断其中的字符是否是数字字符并提取int,
第一个while保证提取到的res是数字;第二个while保证提取到的数字res的
全部(防止123的的情况只取走了1).
}
大佬就是大佬啊~膜拜!!!
啊继续加油啊!还有九天!