习题:DZY Loves Math IV(杜教筛)

题目

传送门

思路

\[设s(n,m)=\sum_{i=1}^{n}\varphi(ni)\\ \]

然后显然分类讨论一下

当\(\mu(n)\ne 0\)的时候,那么就意味着将\(n\)进行质因数分解之后,指数都为\(1\)

\[\begin{aligned}s(n,m)&=\sum_{i=1}^{m}\varphi(ni)\\&=\sum_{i=1}^{m}\varphi(\frac{n}{gcd(n,i)})\varphi(igcd(n,i))\\&=\sum_{i=1}^{m}\varphi(\frac{n}{gcd(n,i)})\varphi(i)gcd(n,i)\\&=\sum_{i=1}^{m}\varphi(\frac{n}{gcd(n,i)})\varphi(i)\sum_{d|gcd(n,i)}\varphi(d)\\&=\sum_{i=1}^{m}\varphi(i)\sum_{d|gcd(n,i)}\varphi(\frac{nd}{gcd(n,i)})\\&=\sum_{i=1}^{m}\varphi(i)\sum_{d|gcd(n,i)}\varphi(\frac{n}{d})\\&=\sum_{d|n}\varphi(\frac{n}{d})\sum_{i=1}^{\lfloor\frac{m}{d}\rfloor}\varphi(id)\\&=\sum_{d|n}\varphi(\frac{n}{d})s(d,\lfloor\frac{m}{d}\rfloor)\end{aligned} \]

当\(\mu(n)=0\)的时候

\[对于普通的\varphi(n)=n\prod\frac{p_k-1}{p_k}\\如果有一个数A满足\frac{n}{A}的质因数种类和n的质因数种类一样\\那么\varphi(nA)=An\prod\frac{p_k-1}{p_k}\\假设x是这样的一个数\\\begin{aligned}\sum_{i=1}^{m}\varphi(in)&=\sum_{i=1}^{m}\varphi(ix\frac{n}{x})\\&=\sum_{i=1}^{m}x\varphi(i\frac{n}{x})\\&=x\sum_{i=1}^{m}\varphi(i\frac{n}{x})\\&=x*s(\frac{n}{x},m)\end{aligned} \]

\[\begin{aligned}ans&=\sum_{i=1}^{n}S(i,m)\end{aligned} \]

之后就是\(S(n,m)\)的边界情况,

显然\(m=0\)是边界情况,那么\(S(n,m)=0\)

还有一个情况是\(n=1\),此时就是\(\sum_{i=1}^{m}\varphi(i)\),直接杜教筛处理即可

那么总共的时间复杂度就集中在了计算\(S(n,m)\)这个函数上面

然后观察这个暴力的形式,实际上跟杜教筛的形式是一样的,所以时间复杂度的计算也可以套过来

即时间复杂度为$O(m^{\frac{2}{3}}) $

代码

#include<unordered_map>
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int mod=1e9+7;
int n,m;
int len;
int lenp,pri[100005],mu[1000005],phi[100005];
bool vis[100005];
long long mphi[100005];
long long ans=0;
unordered_map<int,long long> mp[100005];
unordered_map<int,long long> m1;
long long getphi(long long n)
{
    if(n<=len)
        return mphi[n];
    if(m1.count(n))
        return m1[n];
    long long temp=1ll*n*(n+1)/2%mod;
    for(long long l=2,r;l<=n;l=r+1)
    {
        r=min(1ll*n/(n/l),1ll*n);
        temp=(temp-1ll*(r-l+1)*getphi(n/l)%mod)%mod;
    }
    temp=(temp%mod+mod)%mod;
    return m1[n]=temp;
}
void sieve(int n)
{
    len=n;
    mu[1]=1;
    phi[1]=mphi[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(vis[i]==0)
        {
            pri[++lenp]=i;
            phi[i]=i-1;
            mu[i]=-1;
        }
        for(int j=1;j<=lenp&&1ll*pri[j]*i<=n;j++)
        {
            vis[i*pri[j]]=1;
            if(i%pri[j]==0)
            {
                mu[i*pri[j]]=0;
                phi[i*pri[j]]=pri[j]*phi[i];
                break;
            }
            mu[i*pri[j]]=mu[i]*mu[pri[j]];
            phi[i*pri[j]]=phi[i]*phi[pri[j]]%mod;
        }
        mphi[i]=(mphi[i-1]+phi[i])%mod;
    }
}
long long gets(int n,int m)
{
    if(n==1)
        return getphi(m);
    if(m==1)
        return phi[n];
    if(mp[n].count(m))
        return mp[n][m];
    long long temp=0;
    if(mu[n]!=0)
    {
        for(int d=1;d<=min(m,(int)sqrt(n));d++)
        {
            if(n%d==0)
            {
                if(d*d!=n)
                    temp=(temp+phi[d]*gets(n/d,m/(n/d))%mod)%mod;
                temp=(temp+phi[n/d]*gets(d,m/d)%mod)%mod;
            }
        }
    }
    else
    {
        int x=1;
        int t=n;
        for(int i=2;i<=sqrt(n);i++)
        {
            if(n%i==0)
            {
                int e=0;
                while(n%i==0)
                {
                    e++;
                    n/=i;
                }
                if(e>1)
                    x*=i;
            }
        }
        n=t;
        temp=1ll*x*gets(n/x,m)%mod;
    }    
    return mp[n][m]=temp;
}
int main()
{
    cin>>n>>m;
    sieve(100000);  
    for(int i=1;i<=n;i++) 
    {
        ans=(ans+gets(i,m))%mod;
        //cout<<gets(i,m)<<'\n';
    }
    cout<<ans;
    return 0;
}   
上一篇:【ybt金牌导航8-6-5】最小原根


下一篇:【Luogu P4140】奇数国