洛谷P4240 毒瘤之神的考验

有一个结论:\(\varphi(nm)=\frac{\varphi(n)\varphi(m)\gcd(n,m)}{\varphi\left(\gcd(n,m)\right)}\),考虑证明:

\[\large\begin{aligned} \varphi(nm)&=\frac{\varphi(n)\varphi(m)\gcd(n,m)}{\varphi\left(\gcd(n,m)\right)}\\ \varphi(nm)\varphi\left(\gcd(n,m)\right)&=\varphi(n)\varphi(m)\gcd(n,m)\\ \varphi(nm)\varphi\left(\gcd(n,m)\right)&=n\prod_{p\mid n}\frac{p-1}{p}m\prod_{p\mid m}\frac{p-1}{p}\gcd(n,m)\\ \varphi(nm)\varphi\left(\gcd(n,m)\right)&=nm\prod_{p\mid nm}\frac{p-1}{p}\gcd(n,m)\prod_{p\mid n \and p\mid m}\frac{p-1}{p}\\ \end{aligned} \]

化简原式得:

\[\large\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\left(\gcd(i,j)\right)}\\ =&\sum_{d=1}^n\frac{d}{\varphi(d)}\sum_{i=1}^n\varphi(i)\sum_{j=1}^m\varphi(j)\left[ \gcd(i,j)=d \right]\\ =&\sum_{d=1}^n\frac{d}{\varphi(d)}\sum_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor}\varphi(id)\sum_{j=1}^{\left\lfloor\frac{m}{d}\right\rfloor}\varphi(jd)\left[ \gcd(i,j)=1 \right]\\ =&\sum_{d=1}^n\frac{d}{\varphi(d)}\sum_{k=1}^{\left\lfloor\frac{n}{d}\right\rfloor}\mu(k)\sum_{i=1}^{\left\lfloor\frac{n}{kd}\right\rfloor}\varphi(ikd)\sum_{j=1}^{\left\lfloor\frac{m}{kd}\right\rfloor}\varphi(jkd)\\ =&\sum_{T=1}^n\sum_{d\mid T}\mu\left(\frac{T}{d}\right)\frac{d}{\varphi(d)}\sum_{i=1}^{\left\lfloor\frac{n}{T}\right\rfloor}\varphi(iT)\sum_{j=1}^{\left\lfloor\frac{m}{T}\right\rfloor}\varphi(jT)\\ \end{aligned} \]

\(f(n)=\sum\limits_{d\mid n}\mu\left(\frac{n}{d}\right)\frac{d}{\varphi(d)},g(T,i)=\sum\limits_{j=1}^{i}\varphi(ij)\),筛出 \(\mu,\varphi\) 后即可预处理 \(f(n)\),发现 \(g(T,i)\) 中的 \(i\) 只有 \(\left\lfloor\frac{n}{T}\right\rfloor\) 种,于是其也可以预处理。得答案为:

\[\large \sum_{T=1}^nf(T)g\left(T,\left\lfloor\frac{n}{T}\right\rfloor\right)g\left(T,\left\lfloor\frac{m}{T}\right\rfloor\right) \]

考虑数论分块,设 \(s(x,y,n)=\sum\limits_{i=1}^nf(i)g\left(x,i\right)g\left(y,i\right)\),那么每次分块加上的值就为 \(s\left(\left\lfloor\frac{n}{l}\right\rfloor,\left\lfloor\frac{m}{l}\right\rfloor,r\right)-s\left(\left\lfloor\frac{n}{l}\right\rfloor,\left\lfloor\frac{m}{l}\right\rfloor,l-1\right)\)

发现对于比较大的 \(x,y\) 比较少,因此只预处理比较小的 \(x,y\),大的暴力做即可。设阈值为 \(S\),得复杂度为 \(O(n\log n +n S^2 +T(\left\lfloor\frac{n}{S}\right\rfloor+\sqrt n))\)

#include<bits/stdc++.h>
#define maxn 100010
#define maxs 35
#define all 100000
#define p 998244353
using namespace std;
typedef long long ll;
template<typename T> inline void read(T &x)
{
    x=0;char c=getchar();bool flag=false;
    while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    if(flag)x=-x;
}
int T,n,m,S=32,tot;
int pri[maxn];
ll inv[maxn],mu[maxn],phi[maxn],f[maxn];
bool tag[maxn];
vector<ll> g[maxn],s[maxs][maxs];
int mod(int x)
{
    return x>=p?x-p:x;
}
void init(int n)
{
    inv[1]=phi[1]=mu[1]=1;
    for(int i=2;i<=n;++i)
    {
        inv[i]=(p-p/i)*inv[p%i]%p;
        if(!tag[i]) pri[++tot]=i,phi[i]=i-1,mu[i]=p-1;
        for(int j=1;j<=tot;++j)
        {
            int k=i*pri[j];
            if(k>n) break;
            tag[k]=true;
            if(i%pri[j]) phi[k]=phi[i]*phi[pri[j]],mu[k]=p-mu[i];
            else
            {
                phi[k]=phi[i]*pri[j];
                break;
            }
        }
    }
    for(int i=1;i<=n;++i)
        for(int j=i;j<=n;j+=i)
            f[j]=mod(f[j]+mu[j/i]*i%p*inv[phi[i]]%p);
    for(int i=1;i<=n;++i)
    {
        g[i].resize(n/i+1),g[i][0]=0;
        for(int j=1;j<=n/i;++j)
            g[i][j]=mod(g[i][j-1]+phi[i*j]);
    }   
    for(int i=1;i<=S;++i)
    {
        for(int j=1;j<=S;++j)
        {
            s[i][j].resize(min(n/i,n/j)+1),s[i][j][0]=1;
            for(int k=1;k<=min(n/i,n/j);++k)
                s[i][j][k]=mod(s[i][j][k-1]+f[k]*g[k][i]%p*g[k][j]%p);
        }
    }
}
ll solve(int n,int m)
{
    ll v=0;
    if(n>m) swap(n,m);
    for(int i=1;i;++i)
    {
        if(n/i<=S&&m/i<=S)
        {
            for(int l=i,r;l<=n;l=r+1)
            {
                r=min(n/(n/l),m/(m/l));
                v=mod(v+mod(s[n/l][m/l][r]-s[n/l][m/l][l-1]+p));
            }
            return v;
        }
        v=mod(v+f[i]*g[i][n/i]%p*g[i][m/i]%p);
    }
}
int main()
{
    init(all),read(T);
    while(T--) read(n),read(m),printf("%lld\n",solve(n,m));
    return 0;
}
posted @ 2021-01-26 21:45  lhm_liu  阅读(104)  评论(0编辑  收藏  举报