Test God Luogu4240 cancer of Mobius inversion, root partition

Portal


First, there \ (\ varphi (ij of) = \ {FRAC \ varphi (I) \ varphi (J) \ GCD (I, J)} {\ varphi (\ GCD (I, J))} \) , the Euler substituting into the definition of the function can be demonstrated

You can then start to push equation (default \ (n-\ Leq m \) ):

\(\begin{align*} \sum\limits_{i=1}^n \sum\limits_{j=1}^m \varphi(ij) &= \sum\limits_{i=1}^n \sum\limits_{j=1}^m \frac{\varphi(i) \varphi(j) \gcd(i,j)}{\varphi(\gcd(i,j))} \\ &= \sum\limits_{d=1}^n \frac{d}{\varphi(d)} \sum\limits_{i=1}^{\frac{n}{d}} \sum\limits_{j=1}^{\frac{m}{d}} \varphi(id) \varphi(jd) \sum\limits_{p | i , p | j} \mu(p) \\ &= \sum\limits_{d=1}^n \frac{d}{\varphi(d)} \sum\limits_{p=1}^\frac{n}{d} \mu(p) \sum\limits_{i=1}^\frac{n}{dp} \varphi(idp) \sum\limits_{j=1}^\frac{m}{dp} \varphi(jdp) \\ &= \sum\limits_{T=1}^n \sum\limits_{d | T}\frac{d}{\varphi(d)} \mu(\frac{T}{d}) \sum\limits_{i=1}^\frac{n}{T} \varphi(iT) \sum\limits_{j=1}^\frac{m}{T} \mu(jT) \end{align*}\)

\ (f (T) = \ sum \ limits_ {d | T} \ frac {d} {\ varphi (d)} \ mu (\ frac {T} {d}) \) may be \ (O (nlogn) \) pretreatment of the time, and \ (g (p, q) = \ sum \ limits_ {i = 1} ^ p \ varphi (iq) \) is because of the need to meet \ (pq \ leq n \) so that only \ (O (nlogn) \) of \ ((p, q) \ ) method, can be done using a dynamic array (O (nlogn) \) \ pretreatment.

We now request is \ (\ sum \ limits_ {T = 1} ^ nf (T) g (\ frac {n} {T}, T) g (\ frac {m} {T}, T) \) , noted that there are two division block number theory is conceivable, but because the sum is multiplied by three things, so we need pretreatment for \ (\ forall i \ in [ 1,10 ^ 5], \ forall j \ in [1, 10 ^ 5], \ forall k \ in [1, n], \ sum \ limits_ {T = 1} ^ kf (T) g (i, T) g (j, T) \) , complexity is too high to accept, and direct violence only 50pts.

Note that we now have two approaches pre-treatment and violence, although they will TLE, but we can consider the root partition, put them together do.

Consider pretreatment \ (\ forall i \ in [ 1, B], \ forall j \ in [1, B], \ forall k \ in [1, n], \ sum \ limits_ {T = 1} ^ kf ( T) G (I, T) G (J, T) \) , where \ (B \) is a constant. Then we pretreated complexity is \ (O (nB of ^ 2) \) , and the number of Process block, if \ (\ frac {n} { T}, \ frac {m} {T} \ leq B \) is a direct call answer, otherwise the violence computing, because \ (\ frac {n} { T} \ geq B \) implies \ (T \ Leq \ the n-FRAC {} {B} \) , so complexity is \ (O (T \ frac { n} {B}) \) a.

So the overall complexity is \ (O (^ 2 + nB of \ Tn of FRAC {} {B}) \) , when the \ (B = T ^ \ frac {1} {3} \) there is an optimal time complexity \ (O (nT ^ \ FRAC {{2}}. 3) \) .

#include<bits/stdc++.h>
//this code is written by Itst
using namespace std;

const int _ = 1e5 + 7 , MOD = 998244353 , B = pow(10000 , 1.0 / 3) + 1;
int phi[_] , mu[_] , prm[_] , cnt , T , N , M;
int *g[_] , f[_] , ans[B + 3][B + 3][_];
bool nprm[_];

int poww(long long a , int b){
    int times = 1;
    while(b){
        if(b & 1) times = times * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }
    return times;
}

void init(){
    mu[1] = phi[1] = 1;
    for(int i = 2 ; i <= 1e5 ; ++i){
        if(!nprm[i]){
            prm[++cnt] = i; phi[i] = i - 1; mu[i] = -1;
        }
        for(int j = 1 ; i * prm[j] <= 1e5 ; ++j){
            nprm[i * prm[j]] = 1;
            if(i % prm[j] == 0){
                phi[i * prm[j]] = phi[i] * prm[j];
                break;
            }
            phi[i * prm[j]] = phi[i] * (prm[j] - 1);
            mu[i * prm[j]] = -1 * mu[i];
        }
    }
    for(int i = 1 ; i <= 1e5 ; ++i){
        int tms = 1ll * i * poww(phi[i] , MOD - 2) % MOD;
        for(int j = 1 ; j * i <= 1e5 ; ++j)
            f[i * j] = (f[i * j] + 1ll * mu[j] * tms + MOD) % MOD;
    }
    for(int i = 1 ; i <= 1e5 ; ++i){
        g[i] = new int[(int)(1e5 / i) + 1];
        g[i][0] = 0;
        for(int j = 1 ; j * i <= 1e5 ; ++j)
            g[i][j] = (g[i][j - 1] + phi[i * j]) % MOD;
    }
    for(int i = 1 ; i <= B ; ++i)
        for(int j = i ; j <= B ; ++j)
            for(int k = 1 ; j * k <= 1e5 ; ++k)
                ans[i][j][k] = (ans[i][j][k - 1] + 1ll * f[k] * g[k][i] % MOD * g[k][j]) % MOD;
}

void work(){
    cin >> N >> M;
    if(N > M) swap(N , M);
    int sum = 0;
    for(int i = 1 , pi; i <= N ; i = pi + 1){
        pi = min(N / (N / i) , M / (M / i));
        if(N / i <= B && M / i <= B)
            sum = (0ll + sum + ans[N / i][M / i][pi] - ans[N / i][M / i][i - 1] + MOD) % MOD;
        else
            for(int j = i ; j <= pi ; ++j)
                sum = (sum + 1ll * f[j] * g[j][N / j] % MOD * g[j][M / j]) % MOD;
    }
    cout << sum << endl;
}

signed main(){
#ifndef ONLINE_JUDGE
    freopen("in","r",stdin);
    freopen("out","w",stdout);
#endif
    ios::sync_with_stdio(0);
    init();
    cin >> T;
    while(T--) work();
    return 0;
}

Guess you like

Origin www.cnblogs.com/Itst/p/10956445.html