hdu 3972 1 M possible——位运算
多校确实能学到很多东西呀~~~
看了题解,大概意思是说,这个题是在2*n+1个数中找1个数那种问题的加强版。对于这个简单一点的问题,只要把小球的编号依次异或就可以了,这里就不行,于是我们想到开一个31*31的数组,cnt[i][j],表示第i位是1同时第j位也是1的数字的个数。把整个数组模三,于是整个数组里面就剩下多余的两个数a,b了,我们先来考查cnt[i][i] 。如果a==b,那么cnt[i][i]不是零就是二,那么很容易就得出a,b的值。
如果存在i,使得cnt[i][i]==1,那么不妨设只有a在第i位上是1。那么cnt[i][j]就唯一表示的a了。这样就把a求出来了。然后遍历cnt[i][i],把b求出来就行了。
看了下标程,慢慢学会了位运算。。如果不看标程的话我估计就直接把每个数分解到一个数组里面了,汗……
| 2011-08-26 11:16:47 | Accepted | 3972 | 1109MS | 196K | 1128 B | G++ | Tiramitu | 
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 31
using namespace std;
int cnt[MAXN][MAXN],n;
void solve(void)
{
bool single=false;
int singleid;
for(int i=0;i<MAXN;i++)
{
for(int j=0;j<MAXN;j++)
cnt[i][j]%=3;
if(cnt[i][i]==1)
{
singleid=i;
single=true;
}
}
int a=0,b=0;
if(single)
{
for(int i=0;i<MAXN;i++)
{
if(cnt[singleid][i])
a|=(1<<i);
if(cnt[i][i]==2)
b|=(1<<i);
else if(cnt[i][i]==1)
{
if(!cnt[singleid][i])
{
b|=(1<<i);
}
}
}
if(a>b) swap(a,b);
}
else
{
for(int i=0;i<MAXN;i++)
{
if(cnt[i][i])
{
a|=(1<<i);
b|=(1<<i);
}
}
}
printf("%d %d\n",a,b);
}
int main(void)
{
int T;
scanf("%d",&T);
while(T--)
{
memset(cnt,0,sizeof(cnt));
scanf("%d",&n);
for(int v;n--;)
{
scanf("%d",&v);
for(int i=0;i<MAXN;i++)
{
if(v&(1<<i))
{
for(int j=0;j<MAXN;j++)
{
if(v&(1<<j))
cnt[i][j]++;
}
}
}
}
solve();
}
return 0;
}
 
                    
                 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号