毒瘤題---------------##
題目描述
小江在找水題時發現了這樣一道題:在集合中找出 k ( k≤2)個出現了奇數次的正整數 a。
小江:這不是 sort 的水題嗎。
然後他就用暴力水過了這題。
但是這裏,為了避免暴力碾標算的情況,本題卡內存(逃
輸入格式
第一行兩個數 n,k接下來 n 行每行一個正整數表示集合內的元素。
輸出格式
從小到大輸出一行 k 個數,中間用空格分隔。
樣例輸入
3 1 2 2 2
樣例輸出
2
數據範圍與提示
40% 的數據滿足 k=1且 n 有梯度。
100% 的數據保證 n≤3000000。
保證所有數據正好有 k 個數出現了奇數次。內存限制:4 MiB時間限制:1000 ms
對於k為一的情況:
我們只需要用 “ Λ ” ,就可以愉快的得到四十分了。
對於k為二的情況:
仔細想想,如果依然異或所有的數,我們將得到的是兩個答案的異或值。由於兩個數不可能相同,所以異或值必然不為零。
討論異或的每一位可能的組成情況:(假設兩個答案分別為a,b)
1 .異或值為零:a,b此位都為一或都為 0 。
2 .異或值為一:a,b中有且只有一個此位為 1 。
借鑒第一種情況的解法,假設在二進制中 x 的位置上的異或值最終為 1 ,我們只需要將所有數中在 x 位置上不為 0 的數全部異或起來,
就能得到最終的 x 位置上的 1 究竟是 a 還是 b 貢獻的(找到 a 和 b 中在 x 位置上不為 0 的一個答案)。
1 #include<bits/stdc++.h> 2代碼using namespace std; 3 int n,k,x,sum; 4 int t[33]; 5 int main() 6 { 7 scanf("%d%d",&n,&k); 8 for(int i=1;i<=n;++i) 9 { 10 scanf("%d",&x); 11 sum^=x; 12 for(int j=0;j<=30;++j) 13 if(x>>j&1) 14 t[j]^=x; 15 } 16 if(k==1) 17 printf("%d",sum); 18 else 19 { 20 for(int i=30;i>=0;--i) 21 if(sum>>i&1) 22 { 23 printf("%d %d",t[i]^sum,t[i]); 24 break; 25 } 26 } 27 return 0; 28 }
此題加強版-------- k<=500。
對於如此毒瘤的題, hash 就派上用場了。
我們可以將元素全部表示成 a*100000+b的 形式,然後對於每個元素 hash 後存入表中。
再用異或後的a,b 數組嘗試組成題目給的元素,再用 hash 進行判斷以稍微提高點正確性。
然後就可以愉快的 A 掉此題了。
毒瘤題---------------##