L - Round Numbers POJ - 3252
http://poj.org/problem?id=3252
题目描述:
分析:
把数分成二进制数,用数位dp。dp[pos] [num_0] [num_1]表示第pos位0的数量位num_0和1的数量为num_1的数有多少个。
带入模板,记录下num_0和num_1。再讨论下前导0。
如果dp开一维,dp[pos]就可能会重复。就是会出现莫名其妙的问题。
代码:
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<sstream> #include<vector> #include<stack> #include<queue> #include<cmath> #include<map> #include<set> using namespace std; typedef long long ll; ll dp[50][50][50]; int a[50]; ll dfs(int pos,ll n0,ll n1,bool lead,bool limit) { if(pos==0) return n0>=n1; if(!limit&&!lead&&dp[pos][n0][n1]!=-1) return dp[pos][n0][n1]; int up=limit?a[pos]:1; ll ans=0; for(int i=0;i<=up;i++) { bool st=n0>=n1?1:0; if(lead) { if(i>0) ans+=dfs(pos-1,n0,n1+1,0,limit&&i==a[pos]); else ans+=dfs(pos-1,0,0,lead,0); } else { if(i==0) ans+=dfs(pos-1,n0+1,n1,0,limit&&i==a[pos]); else ans+=dfs(pos-1,n0,n1+1,0,limit&&i==a[pos]); } } if(!limit&&!lead) dp[pos][n0][n1]=ans; return ans; } ll solve(ll x) { int pos=0; while(x) { if(x&1) a[++pos]=1; else a[++pos]=0; x>>=1; } return dfs(pos,0,0,1,1); } int main() { memset(dp,-1,sizeof dp); ll l,r; while(~scanf("%lld%lld",&l,&r)) { printf("%lld\n",solve(r)-solve(l-1)); } return 0; }