Problem

定义函数$f_n(k)=\sum_{l_1=1}^n\sum_{l_2=1}^n\dots\sum_{l_k=1}^n(gcd(l_1,l_2,\dots,l_k))^2$

求$S=\sum_{i=2}^kf_n(i)$

答案对$10^9+7$取模

$1 \le n \le 10^9,2 \le k \le 10^{10^5}$

Solution

$f_n(k)=\sum_{g=1}^ng^2\sum_{l_1=1}^n\sum_{l_2=1}^n\dots\sum_{l_k=1}^n[gcd(l_1,l_2,\dots,l_k)==g]$

设$F(x)=\sum_{l_1=1}^n\sum_{l_2=1}^n\dots\sum_{l_k=1}^n[x \mid gcd(l_1,l_2,\dots,l_k)]$

$g(x)=\sum_{l_1=1}^n\sum_{l_2=1}^n\dots\sum_{l_k=1}^n[gcd(l_1,l_2,\dots,l_k)==x]$

$F(x)=\sum_{x \mid d}g(d)=\lfloor\frac{n}{x}\rfloor^k$

$g(x)=\sum_{x|d}\mu(\frac{d}{x})F(d)=\sum_{x \mid d}\mu(\frac{d}{x})\lfloor\frac{n}{d}\rfloor^k$

$f_n(k)=\sum_{g=1}^ng^2\sum_{g \mid d}\mu(\frac{d}{g})\lfloor\frac{n}{d}\rfloor^k$

枚举约数转枚举倍数

有$f_n(k)=\sum_{i=1}^n\lfloor\frac{n}{i}\rfloor^k\sum_{g|i}g^2\mu(\frac{i}{g})$

则$S(n)=\sum_{i=1}^n(\lfloor\frac{n}{i}\rfloor^2+\lfloor\frac{n}{i}\rfloor^3+\dots+\lfloor\frac{n}{i}\rfloor^k)\sum_{g|i}g^2\mu(\frac{i}{g})$

记$F(n)=n^2+n^3+\dots+n^k$

$G(n)=\sum_{d|n}d^2\mu(\frac{n}{d})$

$F(n)$可以通过等比数列求和公式得到,因为$k$比较大,需要在等比数列求和公式中使用欧拉降幂,需要特殊注意的是,当公比是1时答案是$k-1$,此时$k$并非指数,因此需要分别处理指数取模的$k$以及底数取模的$k$

$G(n)=(id^2\ast\mu)(n)$

考虑卷上$I$来消除$\mu$

$(g*G)(n)=((id^2\ast \mu)\ast I)(n)=(id^2\ast(\mu\ast I))(n)$

$(\mu\ast I)(n)=e,(e\ast f)(n)=f$

因此我们得到$(I\ast G)(n)=id^2$

所以对于$SumG(n)=\sum_{i=1}^nG(n)=\sum_{i=1}^ni^2-\sum_{d \mid n}SumG(\lfloor\frac{n}{d}\rfloor)$

预处理前缀和,杜教筛计算即可

对于$G(n)=(id^2\ast\mu)(n)$前缀和的预处理,$G(n)$是积性函数,并且有$G(1)=1$,$G(p)=p^2-1$,$G(p^c)=p^{2c-2}\ast (p^2-1)$

$S(n)=\sum_{i=1}^nF(\lfloor\frac{n}{i}\rfloor)\ast G(i)$

我们对$G$数值分块,通过$SumG$前缀差得到区段和即可计算最终答案$S$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int P = 1e9 + 7;
const int N = 1e6 + 5;
bool notp[N];
int prime[N], pnum, f[N];
ll sum[N], inv6;
void sieve() {
memset(notp, 0, sizeof(notp));
notp[0] = notp[1] = f[1] = 1;
pnum = 0;
for (int i = 2; i < N; i++) {
if (!notp[i]) {
prime[++pnum] = i;
f[i] = (1ll * i * i - 1 + P) % P;
}
for (int j = 1; j <= pnum && 1ll * prime[j] * i < N; j++) {
notp[prime[j] * i] = 1;
if (i % prime[j] == 0) {
f[i * prime[j]] = 1ll * f[i] * prime[j] % P * prime[j] % P;
break;
}
f[i * prime[j]] = 1ll * f[prime[j]] * f[i] % P;
}
}
for (int i = 1; i < N; i++) sum[i] = (sum[i - 1] + f[i]) % P;
}
int phi(int n) {
int ans = n;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
ans = ans / i * (i - 1);
while (n % i == 0) n /= i;
}
}
if (n > 1) ans = ans / n * (n - 1);
return ans;
}
ll sum2(ll x) { return x * (x + 1) % P * (2 * x + 1) % P * inv6 % P; }
unordered_map<ll, ll> mp;
ll S(ll n) {
if (n < N) return sum[n];
if (mp.count(n)) return mp[n];
ll res = sum2(n);
for (ll i = 2, last; i <= n; i = last + 1) {
last = n / (n / i);
res -= (last - (i - 1) + P) % P * S(n / i) % P;
res = (res % P + P) % P;
}
return mp[n] = res;
}
ll mul(ll x, ll y, ll P) {
return (x * y - (ll)(x / (long double)P * y + 1e-3) * P + P) % P;
}
ll powmod(ll a, ll b, ll P) {
ll t = 1;
for (; b; b >>= 1, a = mul(a, a, P))
if (b & 1) t = mul(t, a, P);
return t;
}
ll cal(ll x, int k, int rk) {
if (x == 1) return (rk - 1 + P) % P;
ll res = (x * x % P - powmod(x, k + 1, P) + P) % P;
res = res * powmod((1 - x + P) % P, P - 2, P) % P;
return res;
}
ll solve(int n, int k, int rk) {
ll res = 0;
for (int i = 1, last; i <= n; i = last + 1) {
last = n / (n / i);
res += (S(last) - S(i - 1) + P) % P * cal(n / i, k, rk) % P;
res %= P;
}
return res;
}
char s[N];
int main() {
int mod = phi(P);
inv6 = powmod(6, P - 2, P);
sieve();
int T, n;
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
scanf("%s", s + 1);
int len = strlen(s + 1);
ll k = 0, rk = 0;
for (int i = 1; i <= len; i++) {
rk = mul(rk, 10, P);
rk = (rk + s[i] - '0') % P;
k = mul(k, 10, mod);
k = (k + s[i] - '0') % mod;
}
printf("%lld\n", solve(n, k, rk));
}
return 0;
}