【HDU2089】数位DP

看了这篇题解,写得超级棒。

dp[i][j]表示一共i位,首位为j的数有多少是符合要求的。
用一个k记录上一位。
先把这个数组全都预处理出来,我一开始位数是从0到LEN,但是预处理的时候不是很方便,就换成从1开始了。

然后处理比n小的数有多少符合要求的。
先把n每位拆开存在d数组里,要注意它是从低位开始存的,但是后面我们是从高位往低位扫,所以是它的上一位是6要写成d[i + 1] == 6,我这里错了好久。
从高位往低位扫,比如n = 1346,先加上0xxx,接着加上0xx、1xx、2xx,然后0x、1x、2x、3x,出现了一个4!就退出来好了,后面的都不会符合要求了,不用费事了。
62也差不多。
注意细节就好了。

#include <cstdio>
#include <cstring>
using namespace std;

const int LEN = 7;

int dp[LEN][10], d[LEN];
int n, m;

void prepare()
{
    dp[0][0] = 1;

    for (int i = 1; i <= LEN; i++)
    {
        for (int j = 0; j <= 9; j++)
        {
            if (j != 4)
            {
                for (int k = 0; k <= 9; k++)
                {
                    if (!(j == 6 && k == 2))
                    {
                        dp[i][j] += dp[i - 1][k];
                    }
                }
            }
            //printf("%d %d : %d\n", i, j, dp[i][j]);
        }
    }
}

int solve(int n)
{
    memset(d, 0, sizeof(d));
    int len = 0;
    while (n)
    {
        d[len + 1] = n % 10;
        n /= 10;
        len++;
    }

    int ans = 0;
    for (int i = len; i >= 1; i--)
    {
        for (int j = 0; j < d[i]; j++)
        {
            //if (d[i + 1] != 6 || j != 2) ans += dp[i][j];
            if (!(j == 2 && d[i + 1] == 6)) ans += dp[i][j];
        }
        if (d[i] == 4 || (d[i + 1] == 6 && d[i] == 2)) break;
    }
    return ans;
}

int main()
{
    prepare();
    while (scanf("%d %d", &n, &m))
    {
        if (n == 0 && m == 0) return 0;
        printf("%d\n", solve(m + 1) - solve(n));
    }
    return 0;
}

【我太辣鸡了,对不起。】

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值