数位统计+hdu3972(dbl)

来源:互联网 发布:websocket php 编辑:程序博客网 时间:2024/05/22 04:41

题意:给你3*N+2个数,找出其中两个特别的数

Case 1:两个数相同

  我们只要把所有数字的各个数位的二进制个数保存下来,模3即可

  模剩下的数组里面非零部分必定是2,把二进制还原即可

Case 2:两个数不同

  两个数必定有一个位上面的二进制表示不同

  开一个[i][j]31*31的数组,意思是第i位是1的所有数字第j位为1的个数

  对数组里面的所有元素模3

  接着,有一个很显然的想法,两个数二进制不同,那么必定有一个[i][i]是1

  把i处保存的数还原,得到一个解

  然后还有一个数是不能用同样的方法来找的,因为可能a&b==a

  也就是说,这种方法只能找到b,找不到a

  找a其实只要把[i][i]为2的二进制个数全部减去b的二进制个数,

  生下来的就是a的,还原即可

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<string>using namespace std;const int maxn=32;int dig[maxn];int dp[maxn][maxn],n;int main(){    freopen("in.txt","r",stdin);    int t,x,i,j,k;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        memset(dig,0,sizeof(dig));        memset(dp,0,sizeof(dp));        for(i=0;i<n;i++)        {            scanf("%d",&x);            for(j=0;j<=30;j++)            {                if((1<<j)&x)                {                    dig[j]++;                    for(k=0;k<=30;k++)                        if((1<<k)&x)dp[j][k]++;                }            }        }        int sum=0;        for(i=0;i<=30;i++)            sum+=(1<<i)*(dig[i]%3);        bool flag=false;        for(i=0;i<=30;i++)        {            if(dp[i][i]%3==1)            {flag=true;break;}        }        if(flag)        {            int a=0;            for(j=0;j<=30;j++)                if(dp[i][j]%3)a+=(1<<j);            printf("%d %d\n",min(a,sum-a),max(a,sum-a));        }        else printf("%d %d\n",sum>>1,sum>>1);    }}


0 0
原创粉丝点击