[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(); }
相关文章推荐
- hdu 5418 Victor and World 最短路 floyd 解题报告
- 浙江大学PAT考试1009~1012(1010上帝是冠军。。)
- 使用Java中间MessageDigest该文本MD5加密(Java中间MD5样品加密算法演示)
- 数据仓库原理<1>:数据库与数据仓库
- 搭建园区拓扑
- greenDAO系列1--概要
- Druid连接池四(学习笔记)
- 数据结构之栈的顺序表实现
- Android-ListView详解(SimpleAdapter,ArrayAdapter,BaseAdapter,OnItenClickListener,OnScrollListener)
- Druid连接池三(学习笔记)
- #317 (div.2) D. Minimization
- ubuntu如何切换到root用户(转)
- MyEclipse2014配置Tomcat开发JavaWeb程序JSP以及Servlet
- Linux内核工程导论——前言
- oracle学习笔记——约束条件
- 二叉树三种遍历非递归实现
- 均匀圆并生成三角形内随机点
- oracle学习笔记——索引
- UVa:1611 Crane(贪心)
- 去哪网实习总结:JavaWeb配置404页面(JavaWeb)