1 条题解
-
0
暴力代码
#include <bits/stdc++.h> #define int long long using namespace std; int gcd(int a, int b) { if (b == 0) return a; return gcd(b, a % b); } int lcm(int a, int b) { return a / gcd(a, b) * b; } // 返回 0~x 中符合要求的数的数量 int len, d[15]; // 当前数字是 number,数位 lcm 是 lcm_now int dfs(int now, bool limit, bool zero, int number, int lcm_now) { if (now == 0) return number % lcm_now == 0; int up = limit ? d[now] : 9; int res = 0; for (int num = 0; num <= up; num++) { int lcm_nxt = lcm_now; if (num != 0) lcm_nxt = lcm(lcm_nxt, num); res += dfs(now - 1, limit && (num == d[now]), zero && num == 0, number * 10 + num, lcm_nxt); } return res; } int cal(int x) { len = 1; d[len] = x; while (d[len] >= 10) { d[len + 1] = d[len] / 10; d[len] = d[len] % 10; len++; } return dfs(len, true, true, 0, 1); } signed main() { ios::sync_with_stdio(false); cin.tie(0); int t, A, B; cin >> t; while (t--) { cin >> A >> B; cout << cal(B) - cal(A - 1) << "\n"; } return 0; }
满分代码
直接记忆化显然不行,两个优化:
number
只存不超过模了lcm(1~9)
的余数lcm_now
情况数不多(少于 50 种),只存对应编号,这里我直接开了个map
存编号。
#include <bits/stdc++.h> #define int long long using namespace std; const int LCM19 = 2520; int gcd(int a, int b) { if (b == 0) return a; return gcd(b, a % b); } int lcm(int a, int b) { return a / gcd(a, b) * b; } // lcm_now 可能性不多,分别编号 int tot = 0; map<int, int> lcm_id; // 返回 0~x 中符合要求的数的数量 int len, d[20]; // 当前数字是 number,数位 lcm 是 lcm_now,lcm_now 只有不超过 50 种 int f[20][LCM19 + 5][50]; int dfs(int now, bool limit, bool zero, int number, int lcm_now) { if (now == 0) return number % lcm_now == 0; if (lcm_id[lcm_now] == 0) lcm_id[lcm_now] = ++tot; if (!limit && !zero && f[now][number][lcm_id[lcm_now]] != -1) return f[now][number][lcm_id[lcm_now]]; int up = limit ? d[now] : 9; int res = 0; for (int num = 0; num <= up; num++) { int lcm_nxt = lcm_now; if (num != 0) lcm_nxt = lcm(lcm_nxt, num); res += dfs(now - 1, limit && (num == d[now]), zero && num == 0, (number * 10 + num) % LCM19, lcm_nxt); } if (!limit && !zero) f[now][number][lcm_id[lcm_now]] = res; return res; } int cal(int x) { len = 1; d[len] = x; while (d[len] >= 10) { d[len + 1] = d[len] / 10; d[len] = d[len] % 10; len++; } return dfs(len, true, true, 0, 1); } signed main() { ios::sync_with_stdio(false); cin.tie(0); for (int i = 0; i <= 19; i++) for (int j = 0; j <= LCM19; j++) for (int k = 0; k < 50; k++) f[i][j][k] = -1; int t, A, B; cin >> t; while (t--) { cin >> A >> B; cout << cal(B) - cal(A - 1) << "\n"; } return 0; }
- 1
信息
- ID
- 14245
- 时间
- 4000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- 递交数
- 29
- 已通过
- 9
- 上传者