题意 : 求 ∑ i = 1 N ∑ j = 1 M ϕ ( i j ) ; N , M ≤ 1 0 5 , q ≤ 1 0 4 \sum_{i=1}^{N}{\sum_{j=1}^{M}{\phi(ij)}}; N,M \leq 10^5, q \leq 10^4 ∑i=1N∑j=1Mϕ(ij);N,M≤105,q≤104
设 N ≤ M N \leq M N≤M.
根据 ϕ \phi ϕ的性质 可以得到 ϕ ( i j ) = ϕ ( i ) ϕ ( j ) g c d ( i , j ) ϕ ( g c d ( i , j ) ) \phi(ij)=\frac{\phi(i)\phi(j)gcd(i,j)}{\phi(gcd(i,j))} ϕ(ij)=ϕ(gcd(i,j))ϕ(i)ϕ(j)gcd(i,j)
如果这一步没想到,只能说是莫反做的不够多了…
n m nm nm过大的情况下是没法处理乘积的,而且直接这么看也看不出什么性质来
所以考虑把乘在一起的 i j ij ij分开处理。
于是 ∑ i = 1 N ∑ j = 1 M ϕ ( i j ) = ∑ i = 1 N ∑ j = 1 M ϕ ( i ) ϕ ( j ) g c d ( i , j ) ϕ ( g c d ( i , j ) ) \sum_{i=1}^{N}{\sum_{j=1}^{M}{\phi(ij)}} = \sum_{i=1}^{N}{\sum_{j=1}^{M}{\frac{\phi(i)\phi(j)gcd(i,j)}{\phi(gcd(i,j))}}} ∑i=1N∑j=1Mϕ(ij)=∑i=1N∑j=1Mϕ(gcd(i,j))ϕ(i)ϕ(j)gcd(i,j),
将 g c d ( i , j ) gcd(i,j) gcd(i,j)相关提出来 可以得到
∑ i = 1 N ∑ j = 1 M ϕ ( i ) ϕ ( j ) g c d ( i , j ) ϕ ( g c d ( i , j ) ) = ∑ d = 1 N d ϕ ( d ) ∑ i = 1 N / d ∑ j = 1 M / d ϕ ( i d ) ϕ ( j d ) ∑ e ∣ g c d ( i , j ) μ ( e ) \sum_{i=1}^{N}{\sum_{j=1}^{M}{\frac{\phi(i)\phi(j)gcd(i,j)}{\phi(gcd(i,j))}}}=\sum_{d=1}^{N}{\frac{d}{\phi(d)}\sum_{i=1}^{N/d}{\sum_{j=1}^{M/d}{\phi(id)\phi(jd)}{\sum_{e|gcd(i,j)}{\mu(e)}}}} ∑i=1N∑j=1Mϕ(gcd(i,j))ϕ(i)ϕ(j)gcd(i,j)=∑d=1Nϕ(d)d∑i=1N/d∑j=1M/dϕ(id)ϕ(jd)∑e∣gcd(i,j)μ(e)
常规性地开始枚举 e e e 得到 ∑ d = 1 N d ϕ ( d ) ∑ e = 1 N / d μ ( e ) ∑ i = 1 N / d e ∑ j = 1 M / d e ϕ ( i d e ) ϕ ( j d e ) \sum_{d=1}^{N}{\frac{d}{\phi(d)}\sum_{e=1}^{N/d}{\mu(e){\sum_{i=1}^{N/de}{\sum_{j=1}^{M/de}{\phi(ide)\phi(jde)}}}}} ∑d=1Nϕ(d)d∑e=1N/dμ(e)∑i=1N/de∑j=1M/deϕ(ide)ϕ(jde)
习惯性地枚举 d e de de 得到 ∑ T = 1 N ∑ i = 1 N / T ϕ ( i T ) ∑ j = 1 M / T ϕ ( j T ) ∑ d ∣ T ϕ ( T d ) d ϕ ( d ) \sum_{T=1}^{N}{\sum_{i=1}^{N/T}{\phi(iT)\sum_{j=1}^{M/T}{\phi(jT)}}\sum_{d|T}{\phi(\frac{T}{d})\frac{d}{\phi(d)}}} ∑T=1N∑i=1N/Tϕ(iT)∑j=1M/Tϕ(jT)∑d∣Tϕ(dT)ϕ(d)d
设 f ( T ) = ∑ d ∣ T ϕ ( T d ) d ϕ ( d ) f(T)=\sum_{d|T}{\phi(\frac{T}{d})\frac{d}{\phi(d)}} f(T)=∑d∣Tϕ(dT)ϕ(d)d , G ( N , T ) = ∑ i = 1 N ϕ ( i T ) G(N,T)=\sum_{i=1}^{N}{\phi(iT)} G(N,T)=∑i=1Nϕ(iT), 代入上式得 :
∑ T = 1 N ∑ i = 1 N / T ϕ ( i T ) ∑ j = 1 M / T ϕ ( j T ) ∑ d ∣ T ϕ ( T d ) d ϕ ( d ) = ∑ T = 1 N G ( N / T , T ) G ( M / T , T ) f ( T ) \sum_{T=1}^{N}{\sum_{i=1}^{N/T}{\phi(iT)\sum_{j=1}^{M/T}{\phi(jT)}}\sum_{d|T}{\phi(\frac{T}{d})\frac{d}{\phi(d)}}}=\sum_{T=1}^{N}{G(N/T,T)G(M/T,T)f(T)} ∑T=1N∑i=1N/Tϕ(iT)∑j=1M/Tϕ(jT)∑d∣Tϕ(dT)ϕ(d)d=∑T=1NG(N/T,T)G(M/T,T)f(T)
设 S ( n , i , j ) = ∑ T = 1 n G ( i T , T ) G ( j T , T ) f ( T ) S(n,i,j)=\sum_{T=1}^{n}G(iT,T)G(jT,T)f(T) S(n,i,j)=∑T=1nG(iT,T)G(jT,T)f(T)
那么设 ⌊ N / T ⌋ = = i , ⌊ M / T ⌋ = = j \lfloor{N/T}\rfloor==i,\lfloor{M/T}\rfloor==j ⌊N/T⌋==i,⌊M/T⌋==j时 N N N的最大值为 u p up up,最小值为 d o w n down down 那么
此时的 a n s = S ( u p , i , j ) − S ( d o w n − 1 , i , j ) ans=S(up,i,j) - S(down-1,i,j) ans=S(up,i,j)−S(down−1,i,j)
因为上界是 ⌊ N / T ⌋ \lfloor{N/T}\rfloor ⌊N/T⌋所以 G G G可以用 N l n N NlnN NlnN内全部暴力预处理出来
G ( N , T ) = G ( N − 1 , T ) + ϕ ( N T ) G(N,T)=G(N-1,T)+\phi(NT) G(N,T)=G(N−1,T)+ϕ(NT)
可以预处理一部分 S S S, 其中 S ( N , i , j ) = S ( N − 1 , i , j ) + G ( i N , N ) G ( j N , N ) f ( N ) S(N,i,j)=S(N-1,i,j)+G(iN,N)G(jN,N)f(N) S(N,i,j)=S(N−1,i,j)+G(iN,N)G(jN,N)f(N)
经过计算(调参)可以得到上界 B B B
upd :为啥代码丢到LOJ上就挂的只剩下50了 , 求助。
#include
#include
#include
const int N = 1e5 + 7;
const int lim = 1e5;
const int B = 35;
typedef long long ll;
const int p = 998244353;
inline int max (int a, int b) {
return a > b ? a : b;
}
inline int min (int a, int b) {
return a > b ? b : a;
}
int isp[N], mu[N], phi[N], prime[N], pcnt;
int *G[N], *S[B + 1][B + 1], f[N], inv[N];
inline void init () {
inv[1] = 1, mu[1] = 1, phi[1] = 1;
for (int i = 2; i <= lim; i++) inv[i] = p - (ll)(p / i) * inv[p % i] % p;
for (int i = 2; i <= lim; i++) {
if (!isp[i]) phi[i] = i - 1, mu[i] = -1, prime[++pcnt] = i;
for (int j = 1; j <= pcnt && prime[j] * i <= lim; j++) {
isp[i * prime[j]] = 1;
if (i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j] % p, mu[i * prime[j]] = 0;
break;
}
phi[i * prime[j]] = phi[i] * (prime[j] - 1) % p , mu[i * prime[j]] = -mu[i];
}
}
for (int i = 1; i <= lim; i++) for (int j = 1; i * j <= lim; j++) {
f[i * j] = (f[i * j] + (ll) ((ll)i * inv[phi[i]] % p) % p * mu[j] % p) % p;
}
for (int i = 1; i <= lim; i++) {
int upmax = lim / i;
G[i] = new int [upmax + 1];
G[i][0] = 0;
for (int j = 1; j <= upmax; j++) G[i][j] = (ll)((ll)G[i][j - 1] + (ll)phi[i * j]) % p;
}
for (int j = 1; j <= B; j++) for (int k = 1; k <= B; k++) {
int upmax = (lim / max (j, k));
S[j][k] = new int [upmax + 1];
S[j][k][0] = 0;
for (int i = 1; i <= upmax; i++) {
S[j][k][i] = (ll)((ll)S[j][k][i - 1] + ll((ll)f[i] * G[i][j] % p * G[i][k])) % p;
}
}
}
int main () {
int T;
scanf ("%d", &T);
init ();
while (T--) {
int n, m, tmp;
scanf ("%d%d", &n, &m);
if (n > m) tmp = n, n = m, m = tmp;
ll ans = 0;
for (int i = 1, upmax = m / B; i <= upmax; i++)
ans = (ans + ((ll)f[i] * G[i][n / i] % p * G[i][m / i] % p)) % p;
for (int l = m / B + 1, r; l <= n; l = r + 1) {
r = min (n / (n / l), m / (m / l));
ans = (ans + (ll(S[n / l][m / l][r] - S[n / l][m / l][l - 1]) % p + p) % p) % p;
}
printf ("%lld\n", ans);
}
return 0;
}