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;
    }
}