Files
python/TangDou/AcWing/ShuWei/1086.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

75 lines
2.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 20;
const LL mod = 1e9 + 7;
LL a[N]; // 用于拆分十进制每一位的数组
LL base[N]; // 预处理出的10的幂次方
struct Node {
LL s0; // 满足条件数的个数 Σ(k,1)
LL s1; // 满足条件的数的和 Σ(k,A)
LL s2; // 满足条件的数的平方的和Σ(k,A^2)
} f[N][7][7];
/*
维度1:u: 数位位置
维度2:sum: 前面完成数位的数位和mod 7
维度3:pre: 前面的类前缀和 mod 7
*/
// 枚举位置,每一位加起来的和%7,这个数%7,是不是贴上界
Node dfs(int u, int sum, int pre, bool op) {
// 1、当u==0时,当sum不是7的倍数,并且,pre不是7的倍数时,这个数是合法的,个数记为1返回
// 2、为什么返回的sum==0,pre==0呢?因为这是要返回上一层去算的,这句话还需要仔细体会含义
if (u == 0) return {(sum && pre), 0, 0};
// 记忆化
if (!op && ~f[u][sum][pre].s0) return f[u][sum][pre];
// 上界
int up = op ? a[u] : 9;
// 本状态下u+sum+pre 的统计信息
Node ans = {0, 0, 0};
for (int i = 0; i <= up; i++) {
if (i == 7) continue;
Node ret = dfs(u - 1, (sum + i) % 7, (pre * 10 + i) % 7, op && (i == up));
// 汇集个数
ans.s0 = (ans.s0 + ret.s0) % mod;
// 汇集数字和
ans.s1 = (ans.s1 + ret.s0 * i % mod * base[u - 1] % mod + ret.s1) % mod;
// 汇集数字平方和
ans.s2 = (ans.s2 + i * base[u - 1] % mod * i % mod * base[u - 1] % mod * ret.s0 % mod) % mod;
ans.s2 = (ans.s2 + 2 * i % mod * base[u - 1] % mod * ret.s1 % mod + ret.s2) % mod;
}
// 套路
if (!op) f[u][sum][pre] = ans;
return ans;
}
LL calc(LL x) {
int al = 0;
while (x) a[++al] = x % 10, x /= 10;
return dfs(al, 0, 0, true).s2;
}
int main() {
// 与7无关的数,是数字本身的特性,而且取模是一个固定值,不会因为多输入几次就变化
memset(f, -1, sizeof(f));
// 预处理出10的幂次方【因为涉及到取模,要不这玩意还用预处理?】
base[0] = 1;
for (int i = 1; i < N; i++) base[i] = base[i - 1] * 10 % mod;
int T;
cin >> T;
LL l, r;
while (T--) {
cin >> l >> r;
printf("%lld\n", (calc(r) - calc(l - 1) + mod) % mod); // 操作的每一步都需要注意取模
}
return 0;
}