http://acm.hdu.edu.cn/showproblem.php?pid=3972
题意:输入n(300000),然后输入n个数4字节以内的正整数,输入保证每次取掉3个相同的数之后剩下2个数。。。从小到大输出这两个。。。问题的关键在于内存限制在1M以内,也就是意味着你不能全部保存下来。。。悲剧。。。
分析:喵呜大神就是牛逼啊。。。记录32位每一位出现的次数,以及每两位之间对应出现的次数a[i][j]。。。求完后都对3取余,很明显,为2的就是分给这剩下的两个数,而为1的就不好分了,这时候就要通过a[][]数组来看对应关系了,如果mod3之后为1说明这两位是对应出现的。。。
网上有人记录了每个x的各位,每个x^2的各位,最后通过a+b和a^2+b^2来求。。。牛逼 啊。。
代码:
#include<iostream>
using namespace std;
const int N=35;
int n, cn;
int a[N][N], b[N], c[N];
void cal(int k)
{
int i, j;
for(i=0, cn=0; k>0; i++, k/=2)
{
if(k%2==1)
{
b[i]++;
c[cn++] = i;
}
}
for(i=0; i<cn; i++)
for(j=i+1; j<cn; j++)
{
a[c[i]][c[j]]++;
a[c[j]][c[i]]++;
}
}
int main()
{
int i, j, k, cas, x, y, flag;
scanf("%d", &cas);
while(cas--)
{
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
memset(c, 0, sizeof(c));
scanf("%d", &n);
for(i=0; i<n; i++)
{
scanf("%d", &k);
cal(k);
}
for(i=0; i<32; i++)
b[i] %= 3;
for(i=0; i<32; i++)
for(j=0; j<32; j++)
a[i][j] %= 3;
x = 0;
flag = -1;
for(i=32; i>=0; i--)
{
x *= 2;
if(b[i]==2)
{
x += 1;
b[i]--;
}
else if(b[i]==1)
{
if(flag==-1)
{
x += 1;
b[i]--;
flag = i;
}
else if(a[flag][i]==1)
{
x += 1;
b[i]--;
}
}
}
y = 0;
for(i=32; i>=0; i--)
{
y *= 2;
y += b[i];
}
if(x>y)
swap(x, y);
printf("%d %d\n", x, y);
}
return 0;
}