1. 程式人生 > >洛谷P1633 二進制

洛谷P1633 二進制

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 二進制