P4240 毒瘤之神的考验
求:
∑ i = 1 n ∑ j = 1 m φ ( i j ) \sum_{i=1}^{n}\sum_{j=1}^{m}\varphi(ij) i=1∑nj=1∑mφ(ij)
先要考虑怎么把 φ \varphi φ 转成带有 gcd \gcd gcd 或 lcm \operatorname{lcm} lcm 的形式。
性质: φ ( i j ) = φ ( i ) φ ( j ) gcd ( i , j ) φ ( gcd ( i , j ) ) \varphi(ij)=\frac{\varphi(i)\varphi(j)\gcd(i,j)}{\varphi(\gcd(i,j))} φ(ij)=φ(gcd(i,j))φ(i)φ(j)gcd(i,j)。
证明:
φ
(
i
)
φ
(
j
)
=
i
∏
p
∣
i
p
−
1
p
j
∏
p
∣
j
p
−
1
p
p
∈
p
r
i
m
e
s
=
i
j
∏
p
∣
i
j
p
−
1
p
∏
p
∣
gcd
(
i
,
j
)
p
−
1
p
\begin{aligned} \varphi(i)\varphi(j)&=i\prod_{p|i}\frac{p-1}{p}j\prod_{p|j}\frac{p-1}{p} &p\in primes\\ &=ij\prod_{p|ij}\frac{p-1}{p}\prod_{p|\gcd(i,j)}\frac{p-1}{p} \end{aligned}
φ(i)φ(j)=ip∣i∏pp−1jp∣j∏pp−1=ijp∣ij∏pp−1p∣gcd(i,j)∏pp−1p∈primes
所以有:
φ
(
i
)
φ
(
j
)
gcd
(
i
,
j
)
=
i
j
∏
p
∣
i
j
p
−
1
p
gcd
(
i
,
j
)
∏
p
∣
gcd
(
i
,
j
)
p
−
1
p
=
φ
(
i
j
)
φ
(
gcd
(
i
,
j
)
)
\begin{aligned} \varphi(i)\varphi(j)\gcd(i,j)&=ij\prod_{p|ij}\frac{p-1}{p}\gcd(i,j)\prod_{p|\gcd(i,j)}\frac{p-1}{p}\\ &=\varphi(ij)\varphi(\gcd(i,j)) \end{aligned}
φ(i)φ(j)gcd(i,j)=ijp∣ij∏pp−1gcd(i,j)p∣gcd(i,j)∏pp−1=φ(ij)φ(gcd(i,j))
化简式子,有:
∑
i
=
1
n
∑
j
=
1
m
φ
(
i
j
)
=
∑
i
=
1
n
∑
j
=
1
m
φ
(
i
)
φ
(
j
)
gcd
(
i
,
j
)
φ
(
gcd
(
i
,
j
)
)
=
∑
d
=
1
n
d
φ
(
d
)
∑
i
=
1
n
∑
j
=
1
m
φ
(
i
)
φ
(
j
)
[
g
c
d
(
i
,
j
)
=
d
]
=
∑
d
=
1
n
d
φ
(
d
)
∑
i
=
1
⌊
n
d
⌋
∑
j
=
1
⌊
m
d
⌋
φ
(
i
d
)
φ
(
j
d
)
[
g
c
d
(
i
,
j
)
=
1
]
=
∑
d
=
1
n
d
φ
(
d
)
∑
p
=
1
⌊
n
d
⌋
μ
(
p
)
∑
i
=
1
⌊
n
d
⌋
φ
(
i
d
)
[
p
∣
i
]
∑
j
=
1
⌊
m
d
⌋
φ
(
j
d
)
[
p
∣
j
]
=
∑
d
=
1
n
d
φ
(
d
)
∑
p
=
1
⌊
n
d
⌋
μ
(
p
)
∑
i
=
1
⌊
n
k
d
⌋
φ
(
i
k
d
)
∑
j
=
1
⌊
m
k
d
⌋
φ
(
j
k
d
)
=
∑
T
=
1
n
(
∑
d
∣
T
d
φ
(
d
)
μ
(
T
p
)
)
(
∑
i
=
1
⌊
n
T
⌋
φ
(
i
T
)
)
(
∑
j
=
1
⌊
m
T
⌋
φ
(
j
T
)
)
设
T
=
d
p
\begin{aligned} &\sum_{i=1}^{n}\sum_{j=1}^{m}\varphi(ij)\\ &=\sum_{i=1}^{n}\sum_{j=1}^{m}\frac{\varphi(i)\varphi(j)\gcd(i,j)}{\varphi(\gcd(i,j))}\\ &=\sum_{d=1}^{n}\frac{d}{\varphi(d)}\sum_{i=1}^{n}\sum_{j=1}^{m}\varphi(i)\varphi(j)[gcd(i,j)=d]\\ &=\sum_{d=1}^{n}\frac{d}{\varphi(d)}\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}\varphi(id)\varphi(jd)[gcd(i,j)=1]\\ &= \sum_{d=1}^{n}\frac{d}{\varphi(d)}\sum_{p=1}^{\lfloor\frac{n}{d}\rfloor}\mu(p)\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\varphi(id)[p|i]\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}\varphi(jd)[p|j]\\ &=\sum_{d=1}^{n}\frac{d}{\varphi(d)}\sum_{p=1}^{\lfloor\frac{n}{d}\rfloor}\mu(p)\sum_{i=1}^{\lfloor\frac{n}{kd}\rfloor}\varphi(ikd)\sum_{j=1}^{\lfloor\frac{m}{kd}\rfloor}\varphi(jkd)\\ &=\sum_{T=1}^{n}\left(\sum_{d|T}\frac{d}{\varphi(d)}\mu(\frac{T}{p})\right)\left(\sum_{i=1}^{\lfloor\frac{n}{T}\rfloor}\varphi(iT)\right)\left(\sum_{j=1}^{\lfloor\frac{m}{T}\rfloor}\varphi(jT)\right)& 设 \ T=dp \\ \end{aligned}\\
i=1∑nj=1∑mφ(ij)=i=1∑nj=1∑mφ(gcd(i,j))φ(i)φ(j)gcd(i,j)=d=1∑nφ(d)di=1∑nj=1∑mφ(i)φ(j)[gcd(i,j)=d]=d=1∑nφ(d)di=1∑⌊dn⌋j=1∑⌊dm⌋φ(id)φ(jd)[gcd(i,j)=1]=d=1∑nφ(d)dp=1∑⌊dn⌋μ(p)i=1∑⌊dn⌋φ(id)[p∣i]j=1∑⌊dm⌋φ(jd)[p∣j]=d=1∑nφ(d)dp=1∑⌊dn⌋μ(p)i=1∑⌊kdn⌋φ(ikd)j=1∑⌊kdm⌋φ(jkd)=T=1∑n⎝⎛d∣T∑φ(d)dμ(pT)⎠⎞⎝⎛i=1∑⌊Tn⌋φ(iT)⎠⎞⎝⎛j=1∑⌊Tm⌋φ(jT)⎠⎞设 T=dp
设
f
(
n
)
=
∑
d
∣
n
d
φ
(
d
)
μ
(
n
p
)
f(n)=\sum\limits_{d|n}\frac{d}{\varphi(d)}\mu(\frac{n}{p})
f(n)=d∣n∑φ(d)dμ(pn),线性筛预处理即可,
O
(
n
ln
n
)
\mathcal{O}(n \ln n)
O(nlnn)。
设 g ( k , n ) = ∑ i = 1 n φ ( i , k ) g(k,n)=\sum\limits_{i=1}^{n}\varphi(i,k) g(k,n)=i=1∑nφ(i,k),显然 g ( k , n ) = g ( k , n − 1 ) + φ ( n k ) g(k,n)=g(k,n-1)+\varphi(nk) g(k,n)=g(k,n−1)+φ(nk)。
则原式等于:
∑
T
=
1
n
f
(
T
)
×
g
(
T
,
⌊
n
T
⌋
)
×
g
(
T
,
⌊
m
T
⌋
)
\begin{aligned} \sum_{T=1}^{n}f(T)\times g(T,\lfloor\frac{n}{T}\rfloor)\times g(T,\lfloor\frac{m}{T}\rfloor) \end{aligned}
T=1∑nf(T)×g(T,⌊Tn⌋)×g(T,⌊Tm⌋)
发现整除分块不了,考虑把整个式子设出来:
h
(
a
,
b
,
n
)
=
∑
t
=
1
n
f
(
t
)
×
g
(
t
,
a
)
×
g
(
t
,
b
)
h(a,b,n)=\sum_{t=1}^{n}f(t)\times g(t,a) \times g(t,b)
h(a,b,n)=t=1∑nf(t)×g(t,a)×g(t,b)
容易发现,这其实就是一个差分:
h
(
a
,
b
,
n
)
=
∑
⌊
n
l
⌋
=
⌊
n
r
⌋
and
⌊
m
l
⌋
=
⌊
m
r
⌋
h
(
⌊
n
r
⌋
,
⌊
m
r
⌋
,
r
)
−
h
(
⌊
n
r
⌋
,
⌊
m
r
⌋
,
l
)
h(a,b,n)=\sum_{\lfloor\frac{n}{l}\rfloor=\lfloor\frac{n}{r}\rfloor \operatorname{and} \lfloor\frac{m}{l}\rfloor=\lfloor\frac{m}{r}\rfloor}h(\lfloor\frac{n}{r}\rfloor,\lfloor\frac{m}{r}\rfloor,r)-h(\lfloor\frac{n}{r}\rfloor,\lfloor\frac{m}{r}\rfloor,l)
h(a,b,n)=⌊ln⌋=⌊rn⌋and⌊lm⌋=⌊rm⌋∑h(⌊rn⌋,⌊rm⌋,r)−h(⌊rn⌋,⌊rm⌋,l)
再考虑根号分治,我们设一个阈值
S
S
S,将所有
h
(
1
,
1
,
1
)
∼
h
(
S
,
S
,
n
)
h(1,1,1) \sim h(S,S,n)
h(1,1,1)∼h(S,S,n) 的
h
h
h 值预处理出来。
预处理式子就是:
h
(
j
,
k
,
i
)
=
h
(
j
,
k
,
i
−
1
)
+
f
(
i
)
×
g
(
i
,
j
)
×
g
(
i
,
k
)
h(j,k,i)=h(j,k,i-1)+f(i)\times g(i,j)\times g(i,k)
h(j,k,i)=h(j,k,i−1)+f(i)×g(i,j)×g(i,k)
对于
⌊
n
r
⌋
≤
S
\lfloor\frac{n}{r}\rfloor \leq S
⌊rn⌋≤S 可直接查询。
否则,可知 r ≤ ⌊ n S ⌋ r \leq \lfloor\frac{n}{S}\rfloor r≤⌊Sn⌋,数论分块计算即可。
#include <bits/stdc++.h>
using namespace std;
const int mod = 998244353;
const int S = 50;
const int maxn = 1e5;
bool vis[maxn + 7];
int tot, prime[maxn + 7];
int mu[maxn + 7], phi[maxn + 7], invphi[maxn + 7];
int sum[maxn + 7];
int *g[maxn + 7], *t[100][100];
int qpow(int x, int y)
{
int res = 1;
while (y)
{
if (y & 1)
res = res * (long long)x % mod;
x = x * (long long)x % mod;
y >>= 1;
}
return res;
}
void init()
{
phi[1] = mu[1] = invphi[1] = 1;
for (int i = 2; i <= maxn; i++)
{
if (!vis[i])
prime[++tot] = i, phi[i] = i + (mu[i] = -1);
for (int j = 1; j <= tot && i * prime[j] <= maxn; j++)
{
vis[i * prime[j]] = true;
if (i % prime[j] == 0)
{
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
mu[i * prime[j]] = -mu[i];
}
invphi[i] = qpow(phi[i], mod - 2);
}
for (int pp = 1; pp <= maxn; pp++)
for (int q = pp, d = 1; q <= maxn; q += pp, d++)
sum[q] = (sum[q] + pp * (long long)invphi[pp] % mod * mu[d]) % mod, sum[q] += (sum[q] < 0 ? mod : 0);
for (int i = 1; i <= maxn; i++)
{
g[i] = new int[(maxn / i) + 1], g[i][0] = 0;
for (int j = 1, sb = maxn / i; j <= sb; j++)
g[i][j] = (g[i][j - 1] + phi[i * j]) % mod;
}
for (int j = 1; j <= S; j++)
for (int k = j; k <= S; k++)
{
int len = maxn / max(j, k);
t[j][k] = new int[len + 1], t[j][k][0] = 0;
for (int i = 1; i <= len; i++)
t[j][k][i] = (t[j][k][i - 1] + sum[i] * (long long)g[i][j] % mod * g[i][k] % mod) % mod;
}
}
signed main()
{
init();
int T;
scanf("%d", &T);
while (T--)
{
int n, m, res = 0;
scanf("%d%d", &n, &m);
if (n > m)
swap(n, m);
for (int i = 1, kkk = m / S; i <= kkk; i++)
res = (res + sum[i] * (long long)g[i][n / i] % mod * g[i][m / i] % mod) % mod;
for (int i = m / S + 1, j; i <= n; i = j + 1)
{
j = min(n / (n / i), m / (m / i));
res = (res + t[n / i][m / i][j] - t[n / i][m / i][i - 1]) % mod, res += (res < 0 ? mod : 0);
}
printf("%d\n", res);
}
return 0;
}