L - Round Numbers POJ - 3252

L - Round Numbers

POJ - 3252

http://poj.org/problem?id=3252

题目描述:

求l到r里面二进制数0的数量>=1的数量的数,有多少个。

分析:

把数分成二进制数,用数位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;
}
 

 

posted on 2020-03-15 16:33  Aminers  阅读(68)  评论(0编辑  收藏  举报

导航