码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-10-18 22:06:09      阅读:247      评论:0      收藏:0      [点我收藏+]

标签:题目   src   isp   scanf   ack   100%   clu   nbsp   不可   

题目描述

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

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

标签:题目   src   isp   scanf   ack   100%   clu   nbsp   不可   

原文地址:https://www.cnblogs.com/wyher/p/9813046.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!