Description
-
多测,数据组数为 T T T。
-
给定 常数 k k k 和整数 n , m n, m n,m,计算
[ ∑ i = 1 n ∑ j = 1 m gcd ( i , j ) k ] m o d ( 1 0 9 + 7 ) \left[\sum_{i = 1}^n \sum_{j = 1}^m \gcd(i, j)^k \right] \bmod (10^9 + 7) [i=1∑nj=1∑mgcd(i,j)k]mod(109+7)
- 对于全部的测试点,保证 1 ≤ T ≤ 2 × 1 0 3 , 1 ≤ n , m , k ≤ 5 × 1 0 6 1\le T\le 2\times 10^3, 1\le n, m, k\le 5\times 10^6 1≤T≤2×103,1≤n,m,k≤5×106。
Solution
不妨设
n
≤
m
n\le m
n≤m。
∑
i
=
1
n
∑
j
=
1
m
gcd
(
i
,
j
)
k
=
∑
d
=
1
n
∑
i
=
1
n
∑
j
=
1
m
d
k
[
gcd
(
i
,
j
)
=
d
]
=
∑
d
=
1
n
d
k
∑
i
=
1
⌊
n
d
⌋
∑
j
=
1
⌊
m
d
⌋
[
gcd
(
i
,
j
)
=
1
]
=
∑
d
=
1
n
d
k
∑
i
=
1
⌊
n
d
⌋
∑
j
=
1
⌊
m
d
⌋
∑
p
∣
gcd
(
i
,
j
)
μ
(
p
)
=
∑
d
=
1
n
d
k
∑
p
=
1
n
μ
(
p
)
⌊
n
d
p
⌋
⌊
m
d
p
⌋
=
∑
T
=
1
n
⌊
n
T
⌋
⌊
m
T
⌋
∑
p
∣
T
μ
(
p
)
(
T
p
)
k
=
∑
T
=
1
n
⌊
n
T
⌋
⌊
m
T
⌋
(
μ
∗
Id
k
)
(
T
)
\begin{aligned} \sum_{i = 1}^n \sum_{j = 1}^m \gcd(i, j)^k & = \sum_{d = 1}^n \sum_{i = 1}^n \sum_{j = 1}^m d^k [\gcd(i, j) = d] \\ & = \sum_{d = 1}^n d^k \sum_{i = 1}^{\left\lfloor\frac{n}{d}\right\rfloor} \sum_{j = 1}^{\left\lfloor\frac{m}{d}\right\rfloor} [\gcd(i, j) = 1] \\ & = \sum_{d = 1}^n d^k \sum_{i = 1}^{\left\lfloor\frac{n}{d}\right\rfloor} \sum_{j = 1}^{\left\lfloor\frac{m}{d}\right\rfloor} \sum_{p\mid \gcd(i, j)} \mu(p) \\ & = \sum_{d = 1}^n d^k \sum_{p = 1}^n \mu(p) \left\lfloor\dfrac{n}{dp}\right\rfloor \left\lfloor\dfrac{m}{dp}\right\rfloor \\ & = \sum_{T = 1}^n \left\lfloor\dfrac{n}{T}\right\rfloor \left\lfloor\dfrac{m}{T}\right\rfloor \sum_{p\mid T} \mu(p) \left(\dfrac{T}{p}\right)^k \\ & = \sum_{T = 1}^n \left\lfloor\dfrac{n}{T}\right\rfloor \left\lfloor\dfrac{m}{T}\right\rfloor (\mu * \operatorname{Id}_k)(T) \end{aligned}
i=1∑nj=1∑mgcd(i,j)k=d=1∑ni=1∑nj=1∑mdk[gcd(i,j)=d]=d=1∑ndki=1∑⌊dn⌋j=1∑⌊dm⌋[gcd(i,j)=1]=d=1∑ndki=1∑⌊dn⌋j=1∑⌊dm⌋p∣gcd(i,j)∑μ(p)=d=1∑ndkp=1∑nμ(p)⌊dpn⌋⌊dpm⌋=T=1∑n⌊Tn⌋⌊Tm⌋p∣T∑μ(p)(pT)k=T=1∑n⌊Tn⌋⌊Tm⌋(μ∗Idk)(T)
设
f
(
n
)
=
(
μ
∗
Id
k
)
(
n
)
f(n) = (\mu * \operatorname{Id}_k)(n)
f(n)=(μ∗Idk)(n),由
μ
\mu
μ 与
Id
k
\operatorname{Id}_k
Idk 都是积性函数可得
f
f
f 是积性函数。
考虑 f f f 的线性筛。
- i i i 为质数: f ( i ) = i k − 1 f(i) = i^k - 1 f(i)=ik−1
- p j ∤ i p_j\nmid i pj∤i: f ( i ⋅ p j ) = f ( i ) f ( p j ) f(i\cdot p_j) = f(i) f(p_j) f(i⋅pj)=f(i)f(pj)
- p j ∣ i p_j\mid i pj∣i: f ( i ⋅ p j ) = f ( i ) p j k f(i\cdot p_j) = f(i) p_j^k f(i⋅pj)=f(i)pjk
预处理 O ( n ) \Omicron(n) O(n),整除分块 O ( n ) \Omicron(\sqrt{n}) O(n),总时间复杂度为 O ( n + T n ) \Omicron(n + T \sqrt{n}) O(n+Tn)。
Code
// 18 = 9 + 9 = 18.
#include <iostream>
#include <cstdio>
#define Debug(x) cout << #x << "=" << x << endl
typedef long long ll;
using namespace std;
const int MAXN = 5e6 + 5;
const int N = 5e6;
const int MOD = 1e9 + 7;
int qpow(int a, int b)
{
int base = a, ans = 1;
while (b)
{
if (b & 1)
{
ans = (ll)ans * base % MOD;
}
base = (ll)base * base % MOD;
b >>= 1;
}
return ans;
}
int p[MAXN], xsy[MAXN], f[MAXN], sum[MAXN];
bool vis[MAXN];
void pre(int k)
{
f[1] = sum[1] = 1;
for (int i = 2; i <= N; i++)
{
if (!vis[i])
{
p[++p[0]] = i;
xsy[i] = qpow(i, k);
f[i] = (xsy[i] - 1 + MOD) % MOD;
}
for (int j = 1; j <= p[0] && i * p[j] <= N; j++)
{
vis[i * p[j]] = true;
if (i % p[j] == 0)
{
f[i * p[j]] = (ll)f[i] * xsy[p[j]] % MOD;
break;
}
f[i * p[j]] = (ll)f[i] * f[p[j]] % MOD;
}
sum[i] = (sum[i - 1] + f[i]) % MOD;
}
}
int getsum(int l, int r)
{
return (sum[r] - sum[l - 1] + MOD) % MOD;
}
int block(int n, int m)
{
int res = 0;
for (int l = 1, r; l <= n; l = r + 1)
{
int k1 = n / l, k2 = m / l;
r = min(n / k1, m / k2);
res = (res + (ll)k1 * k2 % MOD * getsum(l, r) % MOD) % MOD;
}
return res;
}
int main()
{
int t, k;
scanf("%d%d", &t, &k);
pre(k);
while (t--)
{
int n, m;
scanf("%d%d", &n, &m);
if (n > m)
{
swap(n, m);
}
printf("%d\n", block(n, m));
}
return 0;
}