BZOJ4407 于神之怒加强版 <莫比乌斯反演>

Problem

于神之怒加强版

Time  Limit:  80  Sec\mathrm{Time\;Limit:\;80\;Sec}
Memory  Limit:  512  MB\mathrm{Memory\;Limit:\;512\;MB}

Description

给下N,M,KN,M,K,计算∑i=1n∑j=1mgcd⁡(i,j)kmod  (109+7)\sum_{i=1}^{n}\sum_{j=1}^{m}\gcd(i,j)^k\mod(10^9+7)的值。

Input

输入有多组数据,输入数据的第一行两个正整数T,KT,K,代表有TT组数据,KK的意义如上所示,下面第22行到第T+1T+1行,每行为两个正整数N,MN,M,其意义如上式所示。

Output

对于每一个询问,输出一行一个数作为回答。

Sample Input

1
2
1 2
3 3

Sample Output

1
20

HINT

1≤N,M,K≤5×106,  1≤T≤20001\le N,M,K\le5\times 10^6,\;1\le T\le2000
官方题解

标签:莫比乌斯反演

Solution

先套路转换出μ\mu:

Ans=∑i=1n∑j=1mgcd⁡(i,j)k=∑d=1min⁡(n,m)dk∑i=1n∑j=1m[gcd⁡(i,j)=d]=∑d=1min⁡(n,m)dk∑i=1⌊nd⌋∑j=1⌊md⌋∑x∣gcd⁡(i,j)μ(x)=∑d=1min⁡(n,m)dk∑x=1⌊min⁡(n,m)d⌋μ(x)⌊nx⋅d⌋⌊mx⋅d⌋=∑t=1min⁡(n,m)∑d=1tdkμ(td)⌊nt⌋⌊mt⌋=∑t=1min⁡(n,m)⌊nt⌋⌊mt⌋∑d=1tdkμ(td)\begin{aligned} Ans&=\sum_{i=1}^{n}\sum_{j=1}^{m}\gcd(i,j)^k\\ &=\sum_{d=1}^{\min(n,m)}d^k\sum_{i=1}^{n}\sum_{j=1}^{m}[\gcd(i,j)=d]\\ &=\sum_{d=1}^{\min(n,m)}d^k\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}\sum_{x|\gcd(i ,j)}\mu(x)\\ &=\sum_{d=1}^{\min(n,m)}d^k\sum_{x=1}^{\lfloor\frac{\min(n,m)}{d}\rfloor}\mu(x)\lfloor\frac{n}{x\cdot d}\rfloor\lfloor\frac{m}{x\cdot d}\rfloor\\ &=\sum_{t=1}^{\min(n,m)}\sum_{d=1}^{t}d^k\mu(\frac{t}{d})\lfloor\frac{n}{t}\rfloor\lfloor\frac{m}{t}\rfloor\\ &=\sum_{t=1}^{\min(n,m)}\lfloor\frac{n}{t}\rfloor\lfloor\frac{m}{t}\rfloor\sum_{d=1}^{t}d^k\mu(\frac{t}{d})\\ \end{aligned}

那么每次询问对于前半部分可以根号分块,随后需要O(1)O(1)计算后半部分的值,因而需要线筛预处理后半部分的值。

令f(t)=∑d=1tdkμ(td)f(t)=\sum_{d=1}^{t}d^k\mu(\frac{t}{d}),t=p1a1×p2q2×⋯plalt=p_1^{a_1}\times p_2^{q_2}\times\cdots p_l^{a_l}
由于y=dky=d^k和y=μ(d)y=\mu(d)均为积性函数,因而ff也为积性函数。
那么就有

f(t)=∏i=1lf(piai)=∏i=1l∑j=0aipij⋅kμ(piaipij)=∏i=1l∑j=0aipij⋅kμ(piai−j)\begin{aligned} f(t)&=\prod_{i=1}^{l}f(p_i^{a_i})\\&=\prod_{i=1}^{l}\sum_{j=0}^{a_i}p_i^{j\cdot k}\mu(\frac{p_i^{a_i}}{p_i^j})\\ &=\prod_{i=1}^{l}\sum_{j=0}^{a_i}p_i^{j\cdot k}\mu(p_i^{a_i-j})\\ \end{aligned}

易知当j∈[0,ai−1)j\in[0,a_i-1)时,均有μ(piai−j)=0\mu(p_i^{a_i-j})=0,因此有

f(t)=∏i=1l∑j=0aipij⋅kμ(piai−j)=∏i=1l(μ(pi)⋅pik⋅(ai−1)+μ(1)⋅pik⋅ai)=∏i=1l(pik⋅ai−pik⋅(ai−1))=∏i=1lpik⋅(ai−1)(pi−1)\begin{aligned} f(t)&=\prod_{i=1}^{l}\sum_{j=0}^{a_i}p_i^{j\cdot k}\mu(p_i^{a_i-j})\\ &=\prod_{i=1}^{l}(\mu(p_i)\cdot p_i^{k\cdot(a_i-1)}+\mu(1)\cdot p_i^{k\cdot a_i})\\ &=\prod_{i=1}^{l}(p_i^{k\cdot a_i}-p_i^{k\cdot(a_i-1)})\\ &=\prod_{i=1}^{l}p_i^{k\cdot(a_i-1)}(p_i-1) \end{aligned}

接下来考虑在线筛中如何处理。
首先,对于所有质数,均有f(p)=pk−1f(p)=p^k-1。
而对于合数,假设当前筛到的数是xx,对于一个比它小的素数pp,有两种情况:

  1. 若p∣xp|x,设pp在xx分解质因数中的次数为aa,那么f(x×p)f(x\times p)相比于f(x)f(x)而言,在含pp的约数中pp的次数都增加了11,否则μ=0\mu=0无贡献。因此k⋅(a−1)k\cdot(a-1)增加了kk,这样总共扩大了pkp^k倍,故f(x×p)=f(x)×pkf(x\times p)=f(x)\times p^k;
  2. 若p∤xp\nmid x,由积性函数可知f(x×p)=f(x)×f(p)f(x\times p)=f(x)\times f(p)。

这样就可以O(nlog⁡n)O(n\log{n})筛出ff的函数值,每次询问O(Tn)O(T\sqrt{n})根号分块,总复杂度O(nlog⁡n+Tn)O(n\log{n}+T\sqrt{n})。

Code

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
#include <bits/stdc++.h>
#define MAX_N 5000000
#define MOD 1000000007
using namespace std;
typedef long long lnt;
template <class T> inline void read(T &x) {
x = 0; int c = getchar(), f = 1;
for (; !isdigit(c); c = getchar()) if (c == 45) f = -1;
for (; isdigit(c); c = getchar()) (x *= 10) += f*(c-'0');
}
lnt k, cnt, ans, f[MAX_N+5], p[MAX_N+5], pri[MAX_N+5]; bool NotPri[MAX_N+5];
lnt PM(lnt x, lnt y) {if (!y) return 1LL; lnt ret = PM(x, y>>1); return (y&1) ? ret*ret%MOD*x%MOD : ret*ret%MOD;}
void init() {
NotPri[1] = true, f[1] = 1;
for (int i = 2; i <= MAX_N; i++) {
if (!NotPri[i]) pri[cnt++] = i, p[i] = PM(i, k), f[i] = p[i]-1;
for (int j = 0; j < cnt; j++) {
if (i*pri[j] > MAX_N) break; NotPri[i*pri[j]] = true;
if (i%pri[j]) f[i*pri[j]] = f[i]*f[pri[j]]%MOD;
else {f[i*pri[j]] = f[i]*p[pri[j]]%MOD; break;}
}
}
for (int i = 2; i <= MAX_N; i++) (f[i] += f[i-1]) %= MOD;
}
int main() {
int T; read(T), read(k), init();
while (T--) {
lnt n, m; read(n), read(m), ans = 0;
for (lnt l = 1, r; l <= min(n, m); l = r+1)
r = min(n/(n/l), m/(m/l)), (ans += (n/l)*(m/l)%MOD*(f[r]-f[l-1]+MOD)%MOD) %= MOD;
printf("%lld\n", ans);
}
return 0;
}