XXXVIII.[CQOI2013]二进制A+B
最后判无解试了很多次才判成功……主要是因为“\(a,b,c\leq2^{30}\)中有个\(\leq\)而不是\(<\)就很烦人。
思路很简单:设\(f[i][j][k][l][0/1]\)表示:
按位DP到第\(i\)位,
\(a,b,c\)中分别用了\(j,k,l\)个\(1\),
并且进位的情况是\(0/1\),
的最小方案。
转移之间枚举这一位\(a,b\)分别填\(1\)还是填\(0\)即可。
复杂度约是\(O(\log^4)\)。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int lim=31;
int a,b,c,f[lim][lim][lim][lim][2],res=0x3f3f3f3f3f3f3f3f;
void read(int &x){
int t;
x=0;
scanf("%lld",&t);
for(int i=0;i<lim;i++)x+=((t>>i)&1);
}
void chmin(int &a,int b){
a=min(a,b);
}
signed main(){
read(a),read(b),read(c),memset(f,0x3f3f3f3f,sizeof(f));
// printf("%d %d %d\n",a,b,c);
f[0][0][1][1][0]=1;
f[0][1][0][1][0]=1;
f[0][1][1][0][1]=0;
f[0][0][0][0][0]=0;
for(int i=0;i<lim-1;i++)for(int j=0;j<=a;j++)for(int k=0;k<=b;k++)for(int l=0;l<=c;l++)for(int p=0;p<2&&j+p<=a;p++)for(int q=0;q<2&&k+q<=b;q++){
chmin(f[i+1][j+p][k+q][l+((p+q)&1)][(p+q)>1],f[i][j][k][l][0]+(((p+q)&1)<<(i+1)));
chmin(f[i+1][j+p][k+q][l+((p+q+1)&1)][(p+q)>0],f[i][j][k][l][1]+(((p+q+1)&1)<<(i+1)));
}
// for(int i=0;i<lim-1;i++)for(int j=0;j<=a;j++)for(int k=0;k<=b;k++)for(int l=0;l<=c;l++)for(int m=0;m<2;m++)printf("%d %d %d %d %d:%d\n",i,j,k,l,m,f[i][j][k][l][m]);
for(int i=0;i<lim;i++)res=min(res,f[i][a][b][c][0]);
printf("%lld\n",res>(0x7f7f7f7f)?-1:res);
return 0;
}