CF279E Beautiful Decomposition 题解 动态规划
题目链接:http://codeforces.com/problemset/problem/279/E
题目大意
给定一个
问:最少需要几个二的幂?
解题思路
首先不难观察每个二的幂最多使用一次(因为对于某个
然后我们来看二进制数的最高位,假设最高位对应的是
可以发现加上
- 如果我们选择加上
2^k ,则我们面临的是是剩余的那些位; - 如果我们选择加上
2^{k+1} ,则我们面临的是m = 2^{k+1} - n (其中n 是当前的数值,因为加上了2^{k+1} ,所以剩余的m = 2^{k+1} - n 就是应该减去的了,因为因为仅仅变换了一下正负号,m 对应的次数是不会有变化的)—— 这里我们将m 称作n 的补码(注意:k 的值是不需要定义的,因为k 就是n 的二进制表示中的最高位)
然后我们来看状态
所以在我们正式的处理过程中我们只需要处理
定义
具体实现时状态略有调整(我的下标从小到大来的)
示例程序:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 5;
char s[maxn];
int n, dp[2][maxn];
int main() {
scanf("%s", s+1);
n = strlen(s+1);
dp[0][1] = (s[1] == '1');
dp[1][1] = 1; // 一开始 2^{k+1} 边反码至少要一次
for (int i = 2; i <= n; i++) {
if (s[i] == '0') {
dp[0][i] = dp[0][i-1];
dp[1][i] = min(dp[1][i-1], dp[0][i-1]) + 1;
}
else { // s[i] == '1'
dp[1][i] = dp[1][i-1];
dp[0][i] = min(dp[1][i-1], dp[0][i-1]) + 1;
}
}
printf("%d\n", dp[0][n]);
return 0;
}