2015弱校聯萌十一大決戰之背水一戰 D. Divide 二進位制思維題

life4711發表於2015-10-07

http://www.bnuoj.com/v3/contest_show.php?cid=6869#problem/D

Alice and Bob has found a island of treasure in byteland! They find N kinds of treasures on the island, and each kind of treasure has a certain number, and as in byteland, the value of each treasure will be a power of 2, such as 1,2,4,8 ...

Now the only problem is how to divide treasures fairly, they need to divide the treasures into two parts, and the value of each part is the sum of all treasures' in this part, they want to make the difference between the value of two parts as small as possible, can you help them?

Input


First line of the input is a single integer T(1 <= T <= 20), indicating there are T test cases.

For each test case, the first line contain one integer N(2 <= N <= 10^5), indicate the different kinds of treasures.

Then N line followed, each line will have follow two integer ai(0 <= ai <= 10^5) and xi(0 <= xi <= 10^9), indicate there are xi i-th treasures, and the value of each one is 2^ai.

Output

For each case, you should output a single line, first output "Case #t: ", where t indicating the case number between 1 and T, then a string with only '0' and '1' followed, indicate the minimum difference in binary representation, find more details in samples.

Sample Input

3
2
0 2
2 1
4
0 1
1 1
2 1
3 1
4
0 2
1 1
2 1
3 1

Sample Output

Case #1: 10
Case #2: 1
Case #3: 0

/**
2015弱校聯萌十一大決戰之背水一戰  D. Divide  二進位制思維題
題目大意:給定寫物品每個有2^a[i]重,每種x[i]個,問將二者平均分成兩份,二者的最小差的二進位制表示
解題思路:資料如果小點,就是一個揹包的問題了。首先從低位往高位處理,jin[i]表示第i位有沒有前一位的進位,num[i]表示
          進位後i位置的數,我們找到最前一個該位為1,且並無前一位進位的j,那麼2^j,為一份,其前面的所有為一份,做差
          就可以了。因為如果該位為1但有進位的話,完全可以看出改位為0,前一位為2,則可以分成兩份的。
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn=100010;
int n,a[maxn],jin[maxn];
LL num[maxn],x[maxn];
int main()
{
    int T,tt=0;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        int maxx=-1;
        memset(num,0,sizeof(num));
        for(int i=0;i<n;i++)scanf("%d%lld",&a[i],&x[i]),maxx=max(maxx,a[i]),num[a[i]]+=x[i];
//        printf(">>>before");
//        for(int i=0;i<=maxx;i++)printf("%lld",num[i]);
//        printf("\n");
        memset(jin,0,sizeof(jin));
        for(int i=0;i<=maxx;i++)
        {
            if(num[i]/2)jin[i+1]=1;
            num[i+1]+=num[i]/2;
            num[i]%=2;
        }
//        printf(">>>");
//        for(int i=0;i<=maxx;i++)printf("%lld",num[i]);
//        printf("\n");
        bool flag=0;
        for(int i=maxx;i>=0;i--)
        {
            if(num[i]&&jin[i]==0)
            {
                maxx=i;
                flag=1;
                break;
            }
        }
        printf("Case #%d: ",++tt);
        if(flag==0)
        {
            puts("0");
            continue;
        }
        int i;
        for(i=0;i<maxx;i++)
        {
            if(num[i]==1)
            {
                num[i]=1;
                for(int j=i+1;j<maxx;j++)num[j]^=1;
                break;
            }
        }
        num[maxx]=(i==maxx);
        for(int i=maxx;i>=0;i--)
        {
            if(num[i]==1)
            {
                for(int j=i;j>=0;j--)printf("%lld",num[j]);
                break;
            }
        }
        printf("\n");
    }
    return 0;
}


相關文章