POJ 3252 Round Numbers (数位DP入门)

来源:互联网 发布:冯提莫用什么唱歌软件 编辑:程序博客网 时间:2024/06/10 19:13

题意:求【l,r】 区间内多少个Round Numbers,Round Numbers指的是这个数的二进制数中0的个数大于等于1 的个数.

那么数位DP就很好搞了。

但是有一个细节,在前面的做的题中前导0其实是没有什么影响的,但是对于有些题,比如这个题,前导0就有影响。

因为要纪录0/1的个数,那么对于一个数的二进制数,首位肯定不能为0,那么就必须从第一个非0 的二进制位才能开始计数。

那么就在DFS参数中加入一个lead ,lead==true 表示前导1已经出现过了,那么现在产生的0就要计数.

                                                          lead==false表示前导1还未出现,现在的0不能计数。

那么就是一套板子猛怼就完了,很简单。

#include<stdio.h>#include<algorithm>#include<string>#include<string.h>#include<queue>#include<vector>#include<stack>#include<math.h>#include<map>#include<set>#include<iostream>using namespace std;#define INF 0x7f7f7f7f#define LL long longLL dp[100][100][100],l,r;int a[100];LL dfs(int pos,int cnt0,int cnt1,bool limit,bool lead){    if(pos==-1)    {        if(cnt0>=cnt1)            return 1;        return 0;    }    if(!limit&&dp[pos][cnt0][cnt1]!=-1)        return dp[pos][cnt0][cnt1];    int up=limit? a[pos] : 1;    LL ret=0;    for(int i=0;i<=up;i++)    {        if(lead==true)        {            if(i==0)                ret+=dfs(pos-1,cnt0+1,cnt1,limit&&i==a[pos],true);            else if(i==1)                ret+=dfs(pos-1,cnt0,cnt1+1,limit&&i==a[pos],true);        }        else        {            if(i==0)                ret+=dfs(pos-1,cnt0,cnt1,limit&&i==a[pos],false);            else if(i==1)                ret+=dfs(pos-1,cnt0,cnt1+1,limit&&i==a[pos],true);        }    }    if(!limit)        dp[pos][cnt0][cnt1]=ret;    return ret;}LL solve(LL x){    int pos=0;    while(x)    {        a[pos++]=x%2;        x/=2;    }    return dfs(pos-1,0,0,true,false);}int main(){    memset(dp,-1,sizeof(dp));    while(scanf("%lld%lld",&l,&r)!=EOF)    {        printf("%lld\n",solve(r)-solve(l-1));    }    return 0;}

0 0