Description

给出两个数 \(a,~b\) 求出 \([a~,b]\) 中各位数字之和能整除原数的数的个数。

Limitations

\(1 \leq a,~b \leq 10^{18}\)

Solution

考虑数位DP。

设数字 \(A = \sum_{i = 0}^k a_i \times 10^i\),其数字和 \(B = \sum_{i = 0}^k a_i\)

那么 \(A\) 满足条件即为 \(A \equiv 0 \pmod B\),根据同余的性质,可以将求和符号拆开:

\[\sum_{i = 0}^k (a_i \times 10^i \bmod B)~\equiv~0\pmod B
\]

考虑 \(B\) 事实上很小,在 \(18\) 位数字都是 \(9\) 的时候也不超过 \(200\),因此可以枚举 \(B\)。

设 \(f_{i, j, k}\) 位考虑前 \(i\) 位,前 \(i\) 位对应模 \(B\) 的值为 \(j\),且后面几位的数字和为 \(k\),不顶上界的方案数,转移时枚举当前这一位是几即可。

Code

// luogu-judger-enable-o2
#include <cstdio>
#include <cstring> const int maxn = 70;
const int maxm = 163;
const int maxt = 10; int A[maxn], B[maxn];
ll frog[maxn][maxm][maxm]; int ReadNum(int *p);
ll calc(const int *const num, const int n); int main() {
freopen("1.in", "r", stdin);
int x = ReadNum(A), y = ReadNum(B);
ll _sum = 0, _val = 0, _ten = 1;
for (int i = x - 1; ~i; --i) {
_sum += A[i]; _val += A[i] * _ten;
_ten *= 10;
}
qw(calc(B, y) - calc(A, x) + (!(_val % _sum)), '\n', true);
return 0;
} int ReadNum(int *p) {
auto beg = p;
do *p = IPT::GetChar() - '0'; while ((*p < 0) || (*p > 9));
do *(++p) = IPT::GetChar() - '0'; while ((*p <= 9) && (*p >= 0));
return p - beg;
} ll calc(const int *const num, const int n) {
int dn = n - 1;
if (n <= 1) { return num[0]; }
ll _ret = 0, _ten = 1;
for (int i = 1; i < n; ++i) _ten *= 10;
for (int p = 1; p < maxm; ++p) {
memset(frog, 0, sizeof frog);
ll ten = _ten; int tm = ten % p;
int upc = num[0] * tm % p, left = p - num[0];
for (int i = 1; i < num[0]; ++i) if (p >= i) {
frog[0][i * tm % p][p - i] = 1;
}
for (int i = 1; i < n; ++i) {
int di = i - 1;
tm = (ten /= 10) % p;
for (int j = 0; j < p; ++j) {
for (int k = 0; k < p; ++k) {
for (int h = 0; h < 10; ++h) if ((h + k) <= p) {
int dh = h * tm % p, dj = j >= dh ? j - dh : j - dh + p;
frog[i][j][k] += frog[di][dj][k + h];
}
}
}
for (int j = 1; j < 10; ++j) if (j <= p) {
++frog[i][j * tm % p][p - j];
}
for (int h = 0; h < num[i]; ++h) if (h <= left) {
int dh = h * tm % p;
++frog[i][(upc + dh) % p][left - h];
}
upc = (upc + num[i] * tm) % p; left -= num[i];
}
_ret += frog[dn][0][0];
if ((upc == 0) && (left == 0)) ++_ret;
}
return _ret;
}

Summary

逐字符读入 \(L\) 时,\(L - 1\) 并不方便处理,不如改成 \([1, R] - [1,L] + (L\)是否合法\()\)。

最新文章

  1. docker学习(3) 容器的启动过程
  2. TypedReference
  3. mysql 使用函数
  4. Gradle使用小结
  5. 关于padding与margin的区别
  6. .NET对象与Windows句柄(三):句柄泄露实例分析
  7. jQuery中的Deferred-详解和使用
  8. BZOJ 1034: [ZJOI2008]泡泡堂BNB( 贪心 )
  9. Java8新特性-Lambda表达式
  10. Spring Boot系列(一) Spring Boot介绍和基础POM文件
  11. 3 Steps to Perform SSH Login Without Password Using ssh-keygen &amp; ssh-copy-id
  12. yum下载安装redis
  13. iOS ----------各种判断
  14. [LeetCode] Custom Sort String 自定义排序的字符串
  15. Android之编写测试用例
  16. 编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。 但是要保证汉字不被截半个,如“我ABC”4,应该截为“我AB”,输入“我ABC汉DEF”,6,应该输出为“我ABC”而不是“我ABC+汉的半个”。
  17. sublime text全局搜索,查找对应类插件
  18. python中的排序
  19. 电商项目面试题 及mysql面试题 太难没啥用
  20. JS高级 1

热门文章

  1. SQL ------------ 对表中字段的操作 alter
  2. nohup 启动后台应用
  3. Java学习:Junit简介
  4. 在eclipse中,用maven创建一个web项目工程
  5. node、npm、gulp安装
  6. 微信开放平台apk的应用签名的获取
  7. 关于Ext checkboxfiled 获取值为 on的解决办法
  8. linux centos无法删除网站根目录下的.user.ini解决办法
  9. File类---Day28
  10. 扒一扒那些年我们console过的那些事儿