(没学懂,待填坑)【动态规划】数位动态规划

本文介绍了数位动态规划的概念,强调了记忆化、约束条件和高位前导0的重要性。提供了一些模板题和相关练习,如统计区间内数字的数位之和、数位出现次数,以及解决有限制条件的区间数位问题。通过具体例题解析,帮助理解数位DP的解题思路和应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

知识点

一个讲得很好的blog:洛谷日报第84期:数字组成的奥妙——数位dp

一 . 数位DP

数位DP是与数位相关的一类计数类DP,一般用于统计区间[l,r]满足特定条件的数位元素个数。数位指个位、十位、百位、千位等,数位DP指的就是在数位上进行动态规划。数位DP实质上就是有策略的枚举,子问题求解后进行记忆化搜索即可。

二 . 需要注意

① 记忆化 ②约束条件 ③高位前导0

三 . 数位DP模板

int dfs(int pos,int limit,int lead,int sum...各种限制)
//pos表示填数到了第几位,limit表示有无上界限制,lead表示有无前导0 
{
    if(!pos)    return sum;//边界条件 
    if(!limit&&!lead&&dp[pos][...]!=-1)//如果搜过并且没有上界限制和前导0,这一位可以随便填 
    return dp[pos][...];//记忆化搜索 
    int top=limit?a[pos]:9;
    //如果前一位有限制(或填到了最高位)那么这一位不能超过a这一位的大小,否则0~进制数-1随便取 
    int res=0; 
    for(int i=0;i<=top;i++)
    {
        if(...)//限制条件 
        res+=DFS(pos-1,limit&&(i==top),lead&&!i,...);
      //如果所在位置位已经枚举到上界就把上界往后传,上一位有前导0而且这一位是0,那么下一位有前导0 
    } 
    if(!limit&&!lead)dp[pos][...]=res;
        //因为如果枚举到上限则答案并不是这一位上所有的和,所以就不更新
	//着重分析这一句话:当有前导0或有上界限制时,下一位有不能填的数,而dp数组记录的是下一位能全部填0~9的数,所以不更新. 
    return res; 
}

int solve(int x)
{
    int num=0;//位数 
    while(x)//这里是预处理出每一位数的上界 
    {
        a[++num]=x%10;
        x=x/10;
    }
    return dfs(num,1,1,...);//是否有前导0和上界限制等,注意通常统计总和的时候,初始化为1 
} 
int main()
{
    cin>>l>>r;
    cout<<solve(r)-solve(l-1)<<endl;
    //可以先求1~r中满足限制的个数,再求1~l-1中满足限制的数的个数,相减即可得区间l~r的数据 
} 

 模板题

1 .统计一个区间的数字的各个数位之和

例题: 洛谷 P4999 烦人的数学作业 / 洛谷 P1836 数页码 

思路:该题要求在区间内的数字各个数位相加所得的和,但是看数据范围1 \leqslant L \leqslant R \leqslant 10^{18},可以发现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值