洛谷P1633 二進制
阿新 • • 發佈:2017-09-01
color 數量 define () 級別 spa 都是 data- 處理
P1633 二進制
題目描述
有三個整數A、B、C,以下用N(2)表示N的二進制(沒有前導0)。
設A(2)、B(2)、C(2)的最大長度為L,你需要構造三個正整數X、Y、Z,滿足以下條件:
(1) X(2)、Y(2)、Z(2)的長度都不超過L。
(2) A(2)與X(2)中1的個數相同。
(3) B(2)與Y(2)中1的個數相同。
(4) C(2)與Z(2)中1的個數相同。
(5) X+Y=Z.。
輸入輸出格式
輸入格式:
第一行包含一個正整數T,表示有T組測試數據。
接下來T行,每行三個正整數A、B、C。
【數據規模】
對於30%的數據中,滿足1<=A、B、C<=100;
對於100%的數據中,滿足1<=T<=10,1<=A、B、C<=2^30。
輸出格式:
輸出共T行,每行一個答案。
輸出最小的Z。如果沒有z則輸出-1
輸入輸出樣例
輸入樣例#1:4 7 6 9 1 1 1 1 1 4 3 3 9輸出樣例#1:
10 -1 2 6
/* 我們考慮三個長度為l的串; 顯然如果這3個串符合條件的話; 我們就只要保證增加2^l級別的值滿足加法原則就好了; 所以我們大力dp; f[i][a][b][c][0/1] i表示位數 a表示x串前i-1個字符所有的1的數量; b,c同理; 0/1表示c串在第i位是1還是0; 預處理 f[1][0][0][0][0]=0;其他都是inf; 轉移就是考慮當前第i位a,b要不要放1; 然後對應的計算c新增的值;*/ #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define N 35 long long f[N][N][N][N][2],a1,b1,c1; int T,n; int l(long long x){ int cnt1=0,cnt2=0; while(x){ cnt1++; if(x&1)cnt2++; x>>=1; } n=max(n,cnt1);return cnt2; } int main(){ scanf("%d",&T); while(T--){ cin>>a1>>b1>>c1;n=0; int A=l(a1),B=l(b1),C=l(c1); memset(f,127/3,sizeof(f)); f[1][0][0][0][0]=0; for(int i=1;i<=n;i++){ for(int a=0;a<=A;a++) for(int b=0;b<=B;b++) for(int c=0;c<=C;c++){ long long v=f[i][a][b][c][0]; f[i+1][a][b][c][0]=min(f[i+1][a][b][c][0],v); f[i+1][a+1][b+1][c][1]=min(f[i+1][a+1][b+1][c][1],v+(1<<i)); f[i+1][a+1][b][c+1][0]=min(f[i+1][a+1][b][c+1][0],v+(1<<(i-1))); f[i+1][a][b+1][c+1][0]=min(f[i+1][a][b+1][c+1][0],v+(1<<(i-1))); v=f[i][a][b][c][1]; f[i+1][a][b][c+1][0]=min(f[i+1][a][b][c+1][0],v); f[i+1][a+1][b+1][c+1][1]=min(f[i+1][a+1][b+1][c+1][1],v+(1<<i)); f[i+1][a+1][b][c][1]=min(f[i+1][a+1][b][c][1],v+(1<<(i-1))); f[i+1][a][b+1][c][1]=min(f[i+1][a][b+1][c][1],v+(1<<(i-1))); } } if(f[n+1][A][B][C][0]>(1<<30))printf("-1\n"); else cout<<f[n+1][A][B][C][0]<<endl; } }
洛谷P1633 二進制