您的位置:首页 > 其它

[CQOI2013]二进制a+b

2015-08-23 14:30 351 查看

题意

给定三个整数a,b,ca,b,c,把它们写成无前导00的二进制整数。以位数最多的为基准,其它数在前面添加前导0。将它们的各位进行重排,得到a′,b′,c′,使a′+b′=c′a',b',c',使a' + b' = c'。求最小的c′c',无解输出−1-1。

a,b,c≤230a,b,c \le 2^{30}

TimeTime Limits:2000msLimits : 2000ms

MemoryMemory Limits:512000KBLimits : 512000KB

分析

a,b,ca,b,c在二进制下最多只有3030位,我们可以考虑数位dpdp。

将a,b,ca,b,c转化成二进制数,na,nb,ncna,nb,nc分别为它们二进制下11的个数。设f[l][i][j][k][p]f[l][i][j][k][p]为a′+b′a' + b'与c′c'在二进制下从第ll位一直到第11位都相等,用了i个a的1,j个b的1,k个c的1i个a的1,j个b的1,k个c的1,此时a′+b′a'+b'在第l+1l+1位的进位为p(p∈[0,1])p(p∈[0,1]),当前c′c'的最小值。

那么递推公式也比较好想,每做到一位,枚举状态,看它这位放不放aa的11,bb的11或cc的11,每次转移时保证a′+b′和c′a'+b'和c'的该位相等,放11时注意下最小值的增量就行了。

代码

#include <cstdio>
#include <cstring>
using namespace std;

const int N = 32;
int n,na,nb,nc,ans;
int a,b,C,c
;
int tar
;
int f

[2];

int max(int a,int b) {
return a > b ? a : b;
}

void init() {
scanf("%d%d%d",&a,&b,&C);
int cur = 0;
while (C) {
cur ++;
if (C & 1) nc ++;
C >>= 1;
}
n = cur,cur = 0;
while (a) {
cur ++;
if (a & 1) na ++;
a >>= 1;
}
n = max(n,cur),cur = 0;
while (b) {
cur = 0;
if (b & 1) nb ++;
b >>= 1;
}
n = max(n,cur);
}

int min(int a,int b) {
if (a == -1) return b;
if (b == -1) return a;
return a < b ? a : b;
}

bool solve() {
memset(f,255,sizeof(f));
int Inf = f[0][0][0][0][0];
f[0][0][0][0][0] = 0;
for (int l = 0;l < n;l ++) {
for (int i = 0;i <= na;i ++) {
for (int j = 0;j <= nb;j ++) {
for (int k = 0;k <= nc;k ++) {
for (int p = 0;p < 2;p ++) if (f[l][i][j][k][p] != -1) {
if (p == 0 || p == 1 && k < nc) f[l + 1][i][j][k + p][0] = min(f[l + 1][i][j][k + p][0],f[l][i][j][k][p]);
if (!p) {
if (i < na && j < nb) f[l + 1][i + 1][j + 1][k][1] = min(f[l + 1][i + 1][j + 1][k][1],f[l][i][j][k][0] + c[l + 1]);
if (i < na && k < nc) f[l + 1][i + 1][j][k + 1][0] = min(f[l + 1][i + 1][j][k + 1][0],f[l][i][j][k][0] + c[l]);
if (j < nb && k < nc) f[l + 1][i][j + 1][k + 1][0] = min(f[l + 1][i][j + 1][k + 1][0],f[l][i][j][k][0] + c[l]);
}
else {
if (i < na) f[l + 1][i + 1][j][k][1] = min(f[l + 1][i + 1][j][k][1],f[l][i][j][k][1] + c[l]);
if (j < nb) f[l + 1][i][j + 1][k][1] = min(f[l + 1][i][j + 1][k][1],f[l][i][j][k][1] + c[l]);
if (i < na && j < nb && k < nc) f[l + 1][i + 1][j + 1][k + 1][1] = min(f[l + 1][i + 1][j + 1][k + 1][1],f[l][i][j][k][1] + c[l + 1]);
}
}
}
}
}
}
printf("%d",f
[na][nb][nc][0]);
}

int main() {
init();
c[0] = 1;
for (int i = 1;i <= n;i ++) c[i] = c[i - 1] * 2;
ans = -1;
solve();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: