1. 程式人生 > >毒瘤題---------------##

毒瘤題---------------##

plain 暴力 esp 輸入格式 round size scan c++ 3-9

題目描述

小江在找水題時發現了這樣一道題:在集合中找出 k ( k≤2)個出現了奇數次的正整數 a。
小江:這不是 sort 的水題嗎。
然後他就用暴力水過了這題。
但是這裏,為了避免暴力碾標算的情況,本題卡內存(逃

輸入格式

第一行兩個數 n,k接下來 n 行每行一個正整數表示集合內的元素。

輸出格式

從小到大輸出一行 k 個數,中間用空格分隔。

樣例輸入

3 1
2
2
2

樣例輸出

2

數據範圍與提示

40% 的數據滿足 k=1n 有梯度。
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 掉此題了。

毒瘤題---------------##