蓝桥 1024 第 2 场算法双周赛 神奇数【算法赛】python解析

1024 第 2 场算法双周赛 神奇数【算法赛】

时间:2023.11.1
题目地址: 神奇数【算法赛】

题目分析

数位dp,可套模板,就是将最后一位固定枚举(1-9),然后求前面所有可能的和。
有个推荐的模板:数位dp万能模板
详见代码

代码

from functools import lru_cache

def deal(s: str):
    n = len(s)
    ans = 0
    for last in range(1, 10):   # 固定最后一位只能为1~9
    	# i 表示当前数的位置
    	# total 存当前位置时的所有位数之和
    	# is_limit 就是判断当前位的上限,比如说100-123,当第一位为1时第二位[0,1,2]中选最高为2。当第一位为零时,第二位无限制0-9.
    	# is_num 预防前导零,也就是前一位有数字,那么后一位就可以从0开始;不然得从1开始,因为前一位没填数字,这一位就变成了第一位。
        @lru_cache(None)  # 记忆化
        def f(i, total, is_limit, is_num):
            if i == n - 1:  # i到最后一位了就是last,可以返回给出结果
                if not is_num or (is_limit and last > int(s[i])): # is_num为False, 那么没数字取模,或者此时的last超过了给出的s的最后一位,也不合法。
                    return 0
                return total % last == 0   # 判断为结果的条件 True==1.
            res = 0
            if not is_num:
                res += f(i+1, total, False, False)
            low = 0 if is_num else 1 # 前一位有数字,那么后一位就可以从0开始;不然得从1开始,因为前一位没填数字,这一位就变成了第一位。
            up = int(s[i]) if is_limit else 9 # 比如说100-123,当第一位为1时第二位[0,1,2]中选最高为2。
            for d in range(low, up+1):
                res += f(i+1, (total+d) % last, is_limit and d == up, True)
                res %= mod
            return res
        ans += f(0, 0, True, False)
        ans %= mod
    f.cache_clear()
    return ans

l = input()
r = input()
mod = 998244353
print((deal(r) - deal(str(int(l) - 1)))%mod)  # 要记得取模
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值