POJ-3252-数位dp

来源:互联网 发布:java访问权限修饰符 编辑:程序博客网 时间:2024/06/08 13:30

题目大意:前一个区间里二进制表示状态下0的个数不小于1的个数的数的个数;

题目解析:定义dp[i][j]表示在i位上0个个数和1的个数的差值的个数,因为会产生负值所以临界值可以设置为32,这道题前导0会有影响,所以需要特别考虑;

AC代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<string>using namespace std;int dp[40][65],n,m,num[40];int dfs(int pos,int sum,bool lead,bool limit){if(pos==-1)return sum>=32;if(!limit&&!lead&&dp[pos][sum]!=-1)return dp[pos][sum];int u=limit?num[pos]:1;int ans=0;for(int i=0;i<=u;i++){if(lead&&i==0) ans+=dfs(pos-1,sum,lead,limit&&i==num[pos]);else ans+=dfs(pos-1,sum+(i==0?1:-1),lead&&i==0,limit&&i==num[pos]);} if(!limit&&!lead)return dp[pos][sum]=ans;return ans;} int cal(int x){int pos=0;while(x){num[pos++]=x&1;x>>=1;}return dfs(pos-1,32,true,true);}int main(){memset(dp,-1,sizeof(dp));while(scanf("%d%d",&n,&m)!=EOF){printf("%d\n",cal(m)-cal(n-1));}}


0 0