其他分享
首页 > 其他分享> > 数位dp模板题--Round Numbers

数位dp模板题--Round Numbers

作者:互联网

数位dp模板题–Round Numbers

Round Numbers

题目大意:
给定一个区间(以十进制给出),计算出处于区间内数字的二进制形式中零的个数大于一的个数的数有几个。
首先数据给的2e9的,所以这题首先得思路就是用数位dp来做

思路:
将给定的数字以二进制的形式储存起来,设定三维的dp数组dp【当前位数】【一的个数】【零的个数】
记忆化搜索,跑DFS就能很轻松的解出来了
PS:这题需要特判前导零的情况。。。。。


#include<iostream>
#include<string.h>
using namespace std;
int dp[101][51][51];     
int digit[101];  					///digit数组储存搜索数字的二进制形式
int dfs(int pos,int num1,int num0,int limit,int lead)      ///pos为当前位数,num1位当前1的个数,num0位当前0的个数,lead为特判的前导零的情况.
{
    if(pos==-1)
    {
        if(num0>=num1)   ///如果位数搜索完毕零的个数大于等于一的个数,这个数字符合条件,返回1,否则返回0
            return 1;
        else
            return 0;
    }
    if(!lead&&!limit&&dp[pos][num1][num0]!=-1)			///对数据进行记忆化
    {
        return dp[pos][num1][num0];
    }
    int ans=0;
    int top=limit?digit[pos]:1;     ///top为本次数据搜索的当前位数能跑到的最大值
    for(int i=0; i<=top; i++)
    {
        if(lead)
        {
            if(i==0)

                ans+=dfs(pos-1,0,0,limit&&i==top,1);		///如果数据前面有很多零,就直接按照这原先的状态跑
            else
                ans+=dfs(pos-1,1,0,limit&&i==top,0);   ///如果在特判前导零中出现了一,就说明可以正式的进行一或零的计数了
        }
        else						///前导零搞完之后就朴素的跑DFS就完了
        {						
            if(i==0)
            {
                ans+=dfs(pos-1,num1,num0+1,limit&&i==top,0);
            }
            else if(i==1)
            {
                ans+=dfs(pos-1,num1+1,num0,limit&&i==top,0);
            }
        }
    }
    if(!lead&&!limit)
        dp[pos][num1][num0]=ans;
    return ans;
}
int solve(int m)   ///对数据的二进制进行存储
{
    memset(digit,0,sizeof(digit));
    int len=0;
    while(m)
    {
        digit[len++]=m%2;
        m/=2;
    }
    return dfs(len-1,0,0,1,1);
}
int a,b;
int main()
{
    memset(dp,-1,sizeof(dp));   ///别忘了这东西。。。。。。
    cin>>a>>b;
    cout<<solve(b)-solve(a-1)<<endl;
    return 0;
}

总之数位dp应该是各种奇葩dp中较为简单的一种了,数位dp的形式大多都是差不多一样的,只要刷题刷到有感觉,解这种题还是比较简单的(相对其他che du zi 的dp来说)…

标签:num0,num1,int,个数,pos,Numbers,Round,dp
来源: https://blog.csdn.net/qq_44145094/article/details/99050256