poj 3252 数位dp(Round Number)

来源:互联网 发布:python cmd命令 编辑:程序博客网 时间:2024/05/16 16:03

题意:输入两个十进制正整数a和b,求闭区间 [a ,b] 内有多少个Round number。所谓的Round Number就是把一个十进制数转换为一个无符号二进制数,若该二进制数中0的个数大于等于1的个数,则它就是一个Round Number。

思路:用dp来做:dp[i][j]表示二进制长度为 i 的数字含 j 个0的个数,比如dp[3][1] = 2(101和110)。做法就是先打表求出dp数组。然后求出a和b各有多少位,之后特判两边,中间直接求。拿样例来说:问10和1100之间的个数。先求出10~11之间的个数,再求出1000~1100之间的个数,然后求出长度为3的总个数。

#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <queue>#include <cstdlib>using namespace std;#define clc(s,t) memset(s,t,sizeof(s))#define N 36int dp[N][N],sum[N];int a,b;void init(){    int i,j;    dp[1][0] = 1;    clc(sum, 0);    for(i = 2;i<=31;i++){        dp[i][0] = 1;        for(j = 1;j<i;j++){            dp[i][j] = dp[i-1][j-1]+dp[i-1][j];            if(j>=(i+1)/2)                sum[i] += dp[i][j];        }    }}int solve(int x,int d){    int i,j,num=0,res=0;    res = sum[d];    num = (d+1)/2;    for(i = d-1;i>0;i--){        if(0 == ((1<<(i-1))&x)){            for(j = num;j<i;j++)                res -= dp[i][j];            num--;        }    }    return res;}int main(){    int i,j,k,res=0;    init();    scanf("%d %d",&a,&b);    for(i = 30;i>=0;i--)        if((1<<i)&a)            break;    if((a&(a-1))==0)        res +=sum[i+1];    else        res += sum[i+1]-solve(a-1,i+1);    for(j = 30;j>=0;j--)        if((1<<j)&b)            break;    for(k = i+2;k<=j;k++)        res += sum[k];    res += solve(b,j+1);    if(i == j)        res -= sum[i+1];    printf("%d\n",res);}


0 0
原创粉丝点击