[NOIP2018 模拟题] 小P的集合(思维)

题目链接:https://syzoj.com/problem/458

 

题目大意:有n个数字,其中有k个数字出现了奇数次,求这k个数字,其中内存只给4MB,k<=2

 

题目思路:由于内存极小,所以很容易想到应该是通过位来得到结果。首先是假如只有一个数字是奇数次,那么很简单直接全异或起来,那些出现偶数次的就全消掉了,剩下来的就是答案。如果有两个的话,就说明我们得到的结果是答案异或的结果,那么就需要得到答案之一才能得到所有答案。答案所具有的特点是,一定存在有一个位是只有奇数个1的,所以我们要是能够得到在该位是1的所有数字的异或结果就能得到这个数字本身(其他都消掉了)。那就开一个32的内存,然后对于每一个x,在他是1的位的位置都异或上x,最后对刚才得到的全异或的结果进行搜索,找到一个为1的位置就把这个位置所对应的异或结果取出来,就是答案之一,与结果再异或就是另一个答案

 

以下是代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
using namespace std;
const int MAXN = 2e4+5;
const int MAXM = 1e5+5;
int a[32];
int main()
{
    int n,k,x,ans;
    while(~scanf("%d%d",&n,&k)){
        memset(a,0,sizeof(a));
        ans=0;
        rep(i,1,n){
            scanf("%d",&x);
            ans^=x;
            rep(j,0,31){
                int temp=1<<j;
                if(temp&x){
                    a[j]^=x;
                }
            }
        }
        if(k==1){
            printf("%d\n",ans);
        }
        else{
            int p=0;
            rep(j,0,31){
                int temp=1<<j;
                if(temp&ans){
                    p=a[j];
                    break;
                }
            }
            int x=ans^p,y=p;
            if(x>y)swap(x,y);
            printf("%d %d\n",x,y);
        }
    }
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值