您的位置:首页 > 其它

POJ 3252 E - Round Numbers(数位dp)(模板)

2016-11-03 17:05 232 查看
题目大意是:"Round Number "被称为其二进制形式中0的个数比1的个数多。求[x,y]区间内“Round Number”的个数。

这道题看起来难,其实理解了就简单了,就是一个二进制的数位dp,只要转化的时候直接转化成二进制,然后记录每个数的1和0的个数,最后输出和就行了

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

int dp[50][50][50],digit[50];
//因为要数0和1的个数,所以要处理一下前导0的问题
int dfs(int len,int first,int num1,int num0,int fp) { //len二进制数的长度,first是不是第一位数,num1 1的个数,num0 0的个数,fp是不是上限
if(!len && num1 <= num0) return 1; //如果0的个数大于等于1,加一
else if(!len) return 0;
if(!fp && !first && dp[len][num1][num0] != -1) return dp[len][num1][num0];
int maxfp = fp ? digit[len] : 1;
int ans = 0;
for(int i = 0;i <= maxfp;i++) {
if(first) {
if(i == 0) ans += dfs(len-1,1,0,0,fp && i == maxfp);
else ans += dfs(len-1,0,num1+1,num0,fp && i == maxfp);
}
else {
if(i == 0) ans += dfs(len-1,0,num1,num0+1,fp && i == maxfp);
else ans += dfs(len-1,0,num1+1,num0,fp && i == maxfp);
}
}
if(!fp) dp[len][num1][num0] = ans;
return ans;
}

int slove(int x) {
int len = 0;
while(x) {
digit[++len] = x%2; //将这个数转化成二进制存到digit里
x /= 2;
}
return dfs(len,1,0,0,1);
}

int main() {
memset(dp,-1,sizeof(dp));
int s,f;
scanf("%d%d",&s,&f);
printf("%d\n",slove(f) - slove(s-1));
}


其实数位dp不是很难,要打开思维,找到套路。orz
加油~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数位dp 算法 poj