新千题计划 12#:[AHOI2009] 同态分布

本文探讨了一个特定的数位DP问题,即在给定范围内寻找所有各位数字之和能整除原数的数。通过枚举各位和并使用动态规划,实现了对这一复杂问题的有效求解。

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

同态分布 给出两个数 a , b a,b a,b,求出 [ a , b ] [a,b] [a,b] 中各位数字之和能整除原数的数的个数。

数位 DP。 其实是水题,是常规操作,但我搞不出来。

由于各位和在变化,无法实时计算原数模各位和的值。因此我们枚举各位和,到达终点时,只有各位和真的为所枚举的数,才能算一种情况。

#include <cstdio>
#include <cstring>
#define F(z, u, v) for(int z = (u), D##z = (v); z <= D##z; ++z)
typedef long long LL;
LL dp[20][183][182]; char num[21];

LL Dfs(char* k, int sum, int p, int mod, bool lim) {
  LL re = 0, &bl = dp[k - num][sum][p]; if(!*k) return sum == mod && !p;
  if(!lim && ~bl) return bl;
  F(i, '0', lim? *k: '9') re += Dfs(k + 1, sum + i - '0',
    (10 * p + i - '0') % mod, mod, lim && i == *k);
  return lim? re: bl = re; }

LL Ans(LL n) {
  int lth = sprintf(num, "%lld", n); LL re = 0;
  F(i, 1, lth * 9) memset(dp, -1, sizeof dp), re += Dfs(num, 0, 0, i, 1);
  return re; }

int main() {
  LL a, b; scanf("%lld%lld", &a, &b);
  printf("%lld", Ans(b) - Ans(a - 1));
  return 0; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值