SP8177-JZPEXT题解
思路简介
很显然,这是一道数位 dp 题目。对于这一类题目,我们可以采用记忆化搜索的方法进行处理。这种方法套路性较强,易于掌握。不难得到,要是这个数能被每一位上的数整除,它一定能被这些数的最小公倍数整除。我们可以将 dp 数组设为三维,
我们注意到这个数只需要能够被每一位上的数整除即可,而
但是,开一个
注意两个坑点:
- 在进行记忆化搜索时,最开始的最小公倍数要设为
而不是 ,否则会得到 RE 的好结果。 - 这道题对代码长度有限制,尽可能写的短一些。
代码
#include <bits/stdc++.h>
typedef long long i64;
const int Mod = 2520;
int T, tot, a[20];
i64 f[20][2600][50], id[2600], l, r;
inline int lcm(int a, int b) { return a * b / std::__gcd(a, b); }
inline i64 dfs(int pos, int num, int mod, bool limit) {
if (!pos) return (num % mod == 0);
if (!limit && ~f[pos][num][id[mod]]) return f[pos][num][id[mod]];
int up = limit ? a[pos] : 9;
i64 res = 0;
for(int i = 0; i <= up; ++i) res += dfs(pos - 1, (num * 10 + i) % Mod, i ? lcm(mod, i) : mod, limit && i == up);
if (!limit) f[pos][num][id[mod]] = res;
return res;
}
inline i64 solve(i64 num) {
int len = 0;
while (num) a[++len] = num % 10, num /= 10;
return dfs(len, 0, 1, 1);
}
int main() {
std::cin >> T;
memset(f, -1, sizeof(f));
for(int i = 1; i <= Mod; ++i) if (!(Mod % i)) id[i] = ++tot;
while (T--) {
std::cin >> l >> r;
std::cout << solve(r) - solve(l - 1) << '\n';
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】