HDU2089 不要62(数位DP入门经典题目)

昨天做了一道很奇怪的数字题,不知道怎么做,今天才知道是数位DP ……我来学习学习。
传送门
大意:给定区间[n,m],求在n到m中没有“62“或“4“的数的个数。如62315包含62,88914包含4,这两个数都是不合法的。

思路:做这道题我们就要用到数位DP了,我们可以线预处理出一个F数组。用F[i,j]代表开头是j的i位数中不含”62”或”4”的数有几个。这样我们很好写出一个状态转移方程F[i,j]=F[i1,k]|j4j=6k2。我们做的时候,从高到低枚举哪一位比n的哪一位小(这是可以为0的,我们枚举的时候不能取等就是因为我们算的是比他小的。比如说我们找一个数52496:首先答案会加上f[5][3]+f[5][2]+f[5][1]+f[5][0]+f[4][1]+f[4][0]然后就不加了,分别表示三开头的五位数,二开头的五位数,一开头的五位数,任意位数非5位数,以五一开头的五位数,以五零开头的五位数)是不是很易懂呢?

上代码:

#include<cstdio>
#include<cstring>
int f[10][10], n, m;
int bit[10];
int dp(int len)
{
    int ans = 0;
    bit[len + 1] = 0;
    for(int i = len; i > 0; i --){
        for(int j = 0; j < bit[i]; j ++){
            if(j == 2 && bit[i+1] == 6) continue;
            ans += f[i][j];
        }
        if(bit[i] == 4||(bit[i] == 2 && bit[i+1] == 6))    //找到了4或者连续的62说明后面的数都是接在4和62后面的,所以直接退出
            break;
    }
    return ans;
}
int main()
{
    f[0][0] = 1;
    for(int i = 1; i <= 7; i ++)
        for(int j = 0; j <= 9; j ++)
        {
            if(j == 4) continue;
            for(int k = 0; k <= 9; k ++)
            {
                if((j == 6 && k == 2) || k == 4) continue;
                f[i][j] += f[i-1][k];
            }
        }
    while(~scanf("%d%d", &n, &m) && n + m) {
        m ++;                 //因为我们只算了[1,r)的,所以上去间 ++
        int t1 = n, t2 = m, l1 = 0, l2 = 0;
        while(t1)
        {
            l1 ++;
            bit[l1] = t1 % 10;
            t1 /= 10;
        }
        t1 = dp(l1);
        while(t2)
        {
            l2 ++;
            bit[l2] = t2 % 10;
            t2 /= 10;
        }
        t2 = dp(l2);
        printf("%d\n", t2 - t1);
    }
    return 0;
}

转载于:https://www.cnblogs.com/geng4512/p/5296920.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值