毒瘤题---------------##

Posted wyher

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了毒瘤题---------------##相关的知识,希望对你有一定的参考价值。

题目描述

小江在找水题时发现了这样一道题:在集合中找出 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 掉此题了。

以上是关于毒瘤题---------------##的主要内容,如果未能解决你的问题,请参考以下文章

毒瘤阅读题 LightOJ - 1220

毒瘤题---------------##

约会安排 (区间合并)毒瘤题

#6537. 毒瘤题加强版再加强版(hash)

poj1475 Pushing Boxes[双重BFS(毒瘤搜索题)]

loj6087 毒瘤题