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; } }
时间: 2024-11-05 12:18:33