题目链接:http://acm.bnu.edu.cn/v3/problem_show.php?pid=24252

ps:比赛的时候这个题目是我写的,但是写了好长最后还是wa。。。赛后参看菊苣代码,好短,队友神回复:思考的多,代码自然短。。。。。。看来还是太笨了/(ㄒoㄒ)/~~

题目大意:有N个物品,每个物品的价值都是2的幂,现在要把这N个物品分成两堆,使两堆物品价值总和差价最小。。。。

思路:对于幂次为K的物品来说,如果幂次为K-1次的物品个数>=2,那么幂次为K的物品是一定可以平分的(如果幂次为k的物品个数为偶数,那么直接分就好了;如果是奇数,那么向k-1借一位,也就是k-1的物品个数减去2),那么从价值最大开始贪心,如果当前物品个数为1,又不能借助幂次小于它的位来补足平分,那么两堆物品价值差最小应该是从这一位开始的。。。。。。

/**************************************************************
    Problem:BNU 24252
    User: youmi
    Language: C++
    Result: Accepted
    Time:561 ms
    Memory:2756 KB
****************************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <cmath>
#include <queue>
#include <deque>
#include <string>
#include <vector>
#define zeros(a) memset(a,0,sizeof(a))
#define ones(a) memset(a,-1,sizeof(a))
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scs(a) scanf("%s",a)
#define sclld(a) scanf("%I64d",&a)
#define pt(a) printf("%d\n",a)
#define ptlld(a) printf("%I64d\n",a)
#define rep0(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define rep_1(i,n) for(int i=n;i>=1;i--)
#define rep_0(i,n) for(int i=n-1;i>=0;i--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define lson (step<<1)
#define rson (lson+1)
#define esp 1e-6
#define oo 0x3fffffff
#define TEST cout<<"*************************"<<endl

using namespace std;
typedef long long ll;

int n;

const int maxn=200000+10;
ll bit[maxn];
bool dv[maxn];
int main()
{
    //freopen("in.txt","r",stdin);
    int T_T;
    scanf("%d",&T_T);
    for(int kase=1;kase<=T_T;kase++)
    {
        printf("Case #%d: ",kase);
        int a,b;
        zeros(bit);
        zeros(dv);
        sc(n);
        int mx=0;
        rep1(i,n)
        {
            sc2(a,b);
            bit[a]+=b;
            mx=Max(mx,a);
        }
        int flag=-1;
        for(int i=0;i<=mx;i++)
        {
            bit[i+1]+=bit[i]>>1;
            if(bit[i]>=2)
                dv[i+1]=1;
            bit[i]%=2;
        }
        for(int i=mx;i>=0;i--)
        {
            if(bit[i]==1&&!dv[i])
            {
                flag=i;
                break;
            }
        }
        if(flag==-1)
        {
            printf("0\n");
            continue;
        }
        for(int i=0;i<=flag;i++)//最高位的1减去低位,相当于一个取反的过程
            bit[i]=1-bit[i];
        bit[0]+=1;
        for(int i=0;i<=flag;i++)
        {
            bit[i+1]=bit[i+1]+(bit[i]>>1);
            bit[i]%=2;
        }
        for(int i=flag;i>=0;i--)//忽略前导0,跟菊苣学的,,,orz
            if(bit[i])
            {
                for(;i>=0;i--)
                    printf("%lld",bit[i]);
            }
        cout<<endl;
    }
    return 0;
}

 

posted on 2015-10-09 13:59  中子星  阅读(257)  评论(0编辑  收藏  举报