首页 > 代码库 > HDU 3972 1 M possible(思维)

HDU 3972 1 M possible(思维)

1 M possible

Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 2048/1024 K (Java/Others)
Total Submission(s): 1031    Accepted Submission(s): 343


Problem Description
There are 3*N+2 nonnegative integers. Except two special integers, the rest 3*N integers can form N triple groups: { Vi, Vj, Vk| Vi=Vj=Vk}, each integer are at most in one triple group.

Your task is to find the two special integers.

Now, suneast is so boring. He wants to compete with you. As there is no computer available for him, he has to find the integers use his eyes! Unbelievable! So just for fairness, your program can access ONLY 1MB memory!

Tips: Impossible itself says 1 M possible ------ Tourist’s quote (a topcoder target member)
 

Input
The first line of the input contains an integer T(T<=3), indicating the number of test cases.

Each case begin with a line containing an integers N(2<=N<=300000, N=2(mod3) ).

The second lines contains N nonnegative integers Vi (1<=Vi<=2147483647).
 

Output
For each test case, print a line containing two integers a, b (a<=b) separate by a blank. a, b is the desire two special integers.
 

Sample Input
2 2 1 2 23 1 3 1 4 5 2 1 1 3 1 4 5 2 1 1 3 1 4 5 2 1 2 1
 

Sample Output
1 2 1 2
 


题目大意:意思很简单,有3*n+2个数,有3*n个数都是三个三个一起出现的,找出剩下的两个数,不过空间只给了1M,可以算下只能开262144个int。不能直接保存。

解题思路:有同学直接是用hash,然后一次散列就可以做。大概一个月前的题目,比赛的时候就想过压缩成进制来做,不过当时想的是三进制,其实二进制更好解决这个问题。其他的都是%3==0,所以只用看最后两个数就可以了,那么如何知道位与位对应关系,我开了一个mp[32][32]的数组来记录位与位对应的关系,如果一个位唯一确定了一个数字,那么直接找其他位与这位有关系的位即可。详见代码。

题目地址:1 M possible

AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;

int cnt[32],pos[32],mp[32][32];

void solve(int x)
{
    int i,j;

    int t=0,p=0;
    while(x)
    {
        if(x&1)
        {
            cnt[p]++;
            pos[t++]=p;
        }
        p++;
        x>>=1;
    }

    for(i=0;i<t;i++)
        for(j=i+1;j<t;j++)
            mp[pos[j]][pos[i]]++;
}

int main()
{
    int tes,n;
    int i,j,x;
    scanf("%d",&tes);

    while(tes--)
    {
        scanf("%d",&n);
        memset(cnt,0,sizeof(cnt));
        memset(pos,0,sizeof(pos));
        memset(mp,0,sizeof(mp));

        while(n--)
        {
            scanf("%d",&x);
            solve(x);
        }

        for(i=0;i<32;i++)
        {
            cnt[i]%=3;
            for(j=0;j<32;j++)
                mp[i][j]%=3;
        }

        int res1,res2;
        res1=res2=0;

        int poi=-1;
        for(i=31;i>=0;i--)
        {
            res1=res1*2;
            if(cnt[i]==2)
            {
                cnt[i]--;
                res1+=1;
            }
            else if(cnt[i]==1&&poi==-1)
            {
                cnt[i]--;
                poi=i;
                res1+=1;
            }
            else if(cnt[i]==1&&mp[poi][i]==1)
            {
                cnt[i]--;
                res1+=1;
            }
        }

        for(i=31;i>=0;i--)
        {
            res2=res2*2;
            if(cnt[i])
            {
                res2+=1;
            }
        }

        if(res1>res2)
        {
            int tmp=res1;
            res1=res2;
            res2=tmp;
        }
        printf("%d %d\n",res1,res2);
    }
    return 0;
}

/*
5
111 111 111 234 5453

328MS	232K
*/