不要62————数位dp(模板题)

博客内容介绍了关于数位动态规划(DP)的一道模板题,详细解析了如何运用数位DP解决这类问题,帮助读者理解数位DP的思路和应用。

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

题目连接

//不带记忆数组

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define Max 1000
using namespace std;
int a[20];
int dfs(int pos,int six, int limit)//位置 上一位是否为 6 和限制
{
    int re = 0;

    if(pos == -1)return 1 ; //统计数


    int up;//上限

    up = limit?a[pos]:9;//上限

    for(int i = 0;i <= up;i++)
    {
        if(i == 4||(six && i == 2))continue;
        else re+= dfs(pos-1, i==6,  limit&&a[pos] == i);

    }



    return re;
}

int solve(int x)//拆分函数
{
    int len = 0;
    while(x)
    {
        int m = x%10;
        x/=10;
        a[len++] = m;
    }
    return dfs(len-1, false, true);


}
int main()
{

    int n, m;
    while(cin>>n>>m&&(n|| m))
    {

        cout<<solve(m)- solve(n-1)<<endl;
    }
    return 0;
}
//带记忆数组

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define Max 1000
using namespace std;
int a[20];
int dp[20][2][2];// 各个下标的意义:数位 上一位是否有6(1 为有, 0 为无) 限制(1为限制, 0 为不限制)
int dfs(int pos,int six, int limit)    //参数的意义(该数的位置 ,上一位是否为 6,该次循环有没有限制)
{


    if(pos == -1)return 1 ; //统计数

    if(dp[pos][six][limit]!= -1) return dp[pos][six][limit];
    int re = 0;



    int up;//上限
    up = limit?a[pos]:9;//判断上限为哪个



    for(int i = 0;i <= up;i++)//循环该位可能出现的数
    {
        if(i == 4||(six && i == 2))continue;//如果存在 4 后 62 后面的不管是什么都ps掉
        else re+= dfs(pos-1, i==6,  limit&&a[pos] == i);//否则后面的数可能符合要求, 下一个数是否有限制的前提是 上一个数 是限制的(即limit 为1),并且上一个数达到了上界

    }



    return dp[pos][six][limit] = re;
}

int solve(int x)//拆分函数
{
    memset(dp , -1, sizeof(dp));
    int len = 0;
    while(x)
    {
        int m = x%10;
        x/=10;
        a[len++] = m;
    }
    return dfs(len-1, false, true);


}
int main()
{

    int n, m;
    while(cin>>n>>m&&(n|| m))
    {

        cout<<solve(m)- solve(n-1)<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值