UESTC 1711 Divide

/*
http://acm.uestc.edu.cn/problem.php?pid=1711&cid=169
题意:岛上有n种宝藏,每一种宝藏有x个,它的价值为2^a。(x<10^9,a<10^5)
现在给出n种宝藏的个数x和价值a,要你将它分成两份是它们差值最小并输出差值。
思路:开始以为是背包问题,但是做不出来,正确的做法是:跟它的价值是2的次方有关系。
假如宝藏有x个,而x是个奇数,那么没办法我们只能把一边多分一个2^a(先保存好,等下再讨论分给谁)。
剩余的我们不分把她它弄成是(x/2)个价值为2^(a+1)的宝藏。(这里我们需要从a最小的开始)这样一直往上推,把宝藏弄成全部是bc[i][0]*2^i的形式,
而bc[i][1]记录是否由下面2^(i-1)生成的(其中bc[i][0]=1(或0),表示有(没有)2^i的这种宝藏,bc[i][1]=1(或0),表示由(不由)2^(i-1)构成)。
我现在又从高位往低位判断,
1、如果2^j不存在,继续往下分配。
2、如果存在则分两种情况讨论
  (1)、这个宝藏是由2^(j-1)构成的,那么我们把这种宝藏分成2^(j-1),平均分配给两边。继续往下分配。
  (2)、如果不是,我们把这个宝藏分配给一边,把比这个宝藏阶层小的分配给另一边。分配结束。
  差值为2^(j)-bc[j-1][0]*2^(j-1)-bc[j-2][0]*2^(j-2)-……-bc[0][0]*2^0;
  输出其对应的2进制即可。
*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct node{
    long long a,x;
}ac[1100000];
long long bc[1100000][2];
bool cmp(node aa,node bb)
{ return aa.a<bb.a;}
int main()
{
    long long t,n,c,cnt=1;
    long long i,j;
    scanf("%lld",&t);
    while(t--)
    {
        scanf("%lld",&n);
        for(i=0;i<n;i++)
        scanf("%lld %lld",&ac[i].a,&ac[i].x);
        sort(ac,ac+n,cmp);
        memset(bc,0,sizeof(bc));
		int len=0;
		for(i=1;i<n;i++)
		if(ac[len].a==ac[i].a) ac[len].x+=ac[i].x;
		else
		{
			len++;
			ac[len].a=ac[i].a;
			ac[len].x=ac[i].x;
		}
        c=0;j=0;
        for(i=0;i<=ac[len].a;i++)
        {
            if(j<n&&i==ac[j].a){
				if(c>0) bc[i][1]=1;
				c+=ac[j].x;
				j++;
				bc[i][0]=c%2;
				c/=2;
			}
			else
			{
               bc[i][0]=c%2;
			   bc[i][1]=1;
               c/=2;
			}
        }
        for(i=ac[len].a;i>0;i--)
		  if(bc[i][0]==0||(bc[i][0]==1&&bc[i][1]==1)) bc[i][0]=0;
		  else
			  break;
        printf("Case #%lld: ",cnt++);
        if(i==0) printf("%lld\n",bc[0][0]);
        else
        {
             c=0;
             for(j=0;j<=i;j++)
             {
                 if(c==0)
                 {
                    bc[j][0]^=c;
                    c=bc[j][0];
                 }
                 else
                 bc[j][0]^=c;
             }
             while(bc[i][0]==0) i--;
             for(j=i;j>=0;j--)
             printf("%lld",bc[j][0]);
             printf("\n");
        }
    }
    return 0;
}

  

posted @ 2012-07-24 15:08  zhuiy  阅读(317)  评论(0编辑  收藏  举报