题目链接: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; }
不为失败找借口,只为成功找方法