題目鏈接:http://lx.lanqiao.cn/problem.page?gpid=T519
問題描述
《審美的歷程》課上有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。
首先自己採用暴力破解的方法寫的,只得了50分,後面的超時。然後開始參考大佬的方法
大佬1:https://blog.csdn.net/weixin_42474261/article/details/87736683
將輸入的0,1數據可看爲二進制數,每一個二進制對應一個獨一的十進制,這樣我們把每一個同學的判斷作爲一個數,然後將該數作爲一個新數組的下標,這樣只要有同學的判斷是相同的,則他們二進制數對應的十進制數也是相同的,同理下標也是相同的,所以下標相同時,下標對應的值加一。
這樣我們就對輸入輸入處理完了。然後開始找判斷完全相反的同學的對數。利用異或這一位運算“^”,如果兩個同學的判斷完全相反,則兩位同學的二進制數異或後爲1。利用這一結論,我們來找同學對數。
首先找到m個1對應十進制數,用來和同學的十進制數異或運算,得到的數,作爲下標,在統計次數的數組中找到對應的值,相加。這樣逐個類推下去,可統計到所有的。
然而改了之後,只得了60分,還時超時。
大佬2:https://blog.csdn.net/qq_42794545/article/details/87939021
題目輸入數據很大,需要用字符流來讀寫數據。不然會超時
改了輸入的方式後,就過了,100分
代碼如下:
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
public class Main {
private static Reader reader;
public static void main(String[] args) {
// Scanner sc = new Scanner(System.in);
// int n = sc.nextInt();
// int m = sc.nextInt();
reader = new InputStreamReader(System.in);
int n = getInt();
int m = getInt();
int[] ind = new int[50001];
int[] res = new int[2000000];
int sum = 0;
for(int i=0;i<n;i++) {
int[] mrr = new int[21];
for(int j=0;j<m;j++) {
mrr[j] = getInt();
}
ind[i] = toDec(mrr, m);
res[ind[i]]++;
}
int max = toSum(m);
for(int i=0;i<n;i++) {
int tmp = ind[i] ^ max;
sum += res[tmp];
}
System.out.println(sum/2);
// Scanner sc = new Scanner(System.in);
// int[][] view = new int[50000][22];
// String[] str0 = new String[50001];
// String[] str1 = new String[50001];
// int n = sc.nextInt();
// int m = sc.nextInt();
// int sum = 0;
// for(int i=0;i<n;i++) {
// for(int j=0;j<m;j++) {
// view[i][j] = sc.nextInt();
// }
// }
// for(int i=0;i<n;i++) {
// str0[i] = toStr0(view[i], m);
// str1[i] = toStr1(view[i], m);
// }
// for(int i=0;i<n;i++) {
// for(int j=i+1;j<n;j++) {
// if(str0[i].equals(str1[j]))
// sum ++;
// }
// }
// System.out.println(sum);
}
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) {
e.printStackTrace();
}
return res;
}
public static int toDec(int[] arr, int m) {
int sum = 0;
int time = 1;
for(int i=m-1;i>=0;i--) {
sum += arr[i] * time;
time *= 2;
}
return sum;
}
public static int toSum(int m) {
int sum = 0;
int time = 1;
while(m!=0) {
sum += time;
time *= 2;
m--;
}
return sum;
}
// public static String toStr0(int[] arr, int m) {
// StringBuilder sb = new StringBuilder();
// for (int i = 0; i < m; i++) {
// sb.append(arr[i]);
// }
// return sb.toString();
// }
// public static String toStr1(int[] arr, int m) {
// StringBuilder sb = new StringBuilder();
// for(int i=0;i<m;i++) {
// if(arr[i] == 0)
// sb.append(1);
// else
// sb.append(0);
// }
// return sb.toString();
// }
}