luogu p4240 毒瘤之神的考验

题意 : 求 ∑ 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=1Nj=1Mϕ(ij);N,M105,q104

N ≤ M N \leq M NM.

根据 ϕ \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=1Nj=1Mϕ(ij)=i=1Nj=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=1Nj=1Mϕ(gcd(i,j))ϕ(i)ϕ(j)gcd(i,j)=d=1Nϕ(d)di=1N/dj=1M/dϕ(id)ϕ(jd)egcd(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)de=1N/dμ(e)i=1N/dej=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=1Ni=1N/Tϕ(iT)j=1M/Tϕ(jT)dTϕ(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)=dTϕ(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=1Ni=1N/Tϕ(iT)j=1M/Tϕ(jT)dTϕ(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(down1,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(N1,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(N1,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;
}

你可能感兴趣的:(题目,莫比乌斯反演)