Codeforces - 95D. Horse Races - 数位dp+大数运算

Horse Races

题目链接

分类dp math

1.题意概述

  • 规定47是幸运数,而且约定一个数是“辛运数字”当且仅当,相邻两个幸运数字的数位距离不超过 k(1k1000) ,现在给定你一个区间 [l,r](1lr101000) ,问你这个区间的幸运数字有多少个,答案取模 109+7

2.解题思路

  • 很显然,这是一道数位dp的题目,两个难点,一个在于大数如何转化,第二个在于如何统计不超过k的距离,第一个我们可以通过读入字符串,然后将字符串倒序就可以实现,但是因为我们是统计的前缀,因此在 l1 时候模拟大数减法不要忘了可能会出现退位现象。而第二个难点,我们可以直接考虑在dfs时候增加一个限制条件看距离上一个距离是否小于 k <script type="math/tex" id="MathJax-Element-5">k</script>即可,细节很多,参见代码:

3.AC代码

int digit[N];
ll dp[N][N][2];
char l[N], r[N];
int k;
int dfs(int len, int p, bool flag, bool limit) {
    if (len == 0) return flag;
    if (limit == 0 && dp[len][p][flag] != -1) return dp[len][p][flag];
    int up = limit ? digit[len] : 9;
    int res = 0;
    rep(i, 0, up + 1) {
        if (i != 4 && i != 7)
            res = (res + dfs(len - 1, max(0, p - 1), flag, limit && i == up)) % mod;
        else res = (res + dfs(len - 1, 1 * k, flag || p, limit && i == up)) % mod;
    }
    if (!limit) dp[len][p][flag] = res;
    return res;
}
inline void solve() {
    int t;
    memset(dp, -1, sizeof dp);
    scanf("%d%d", &t, &k);
    while (t--) {
        scanf("%s%s", l, r);
        int len = strlen(r);
        per(i, 0, len + 1) digit[i] = r[len - i] - '0';
        int ans = dfs(len, 0, 0, 1);
        len = strlen(l);
        per(i, 0, len + 1) digit[i] = l[len - i] - '0';
        digit[1]--;
        for (int i = 1; digit[i] < 0; i++) {
            digit[i] += 10;
            digit[i + 1]--;
        }
        if (digit[len] == 0) len--;
        ans = (ans - dfs(len, 0, 0, 1) + mod) % mod;
        printf("%d\n", ans);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值