1. 程式人生 > 實用技巧 >BZOJ-4916 神犇和蒟蒻(杜教篩)

BZOJ-4916 神犇和蒟蒻(杜教篩)

題目描述

  計算:

\[A=\sum_{i=1}^{n}{\mu (i^2)},B=\sum_{i=1}^{n}{\varphi (i^2)}。 \]

  資料範圍:\(n\leq 10^9\)

分析

  第一問,根據 \(\mu\) 的定義,\(A\) 顯然為 \(1\)

  第二問,\(\varphi(n)=n\times \displaystyle\prod_{i=1}^{k}\Big(1-\frac{1}{p_i}\Big)\),所以 \(\varphi(n^2)=n^2\times \displaystyle\prod_{i=1}^{k}\Big(1-\frac{1}{p_i}\Big)=n\times \varphi(n)\)

  則答案為 \(S(n)=\displaystyle\sum_{i=1}^{n}i\varphi(i)\)

  由於 \(\varphi\ast I=\mathbf{id}\),所以構造 \(h=f\ast g=I\ast\varphi\ast\mathbf{id}=\mathbf{id}\ast \mathbf{id}\)(其中 \(f=I\ast \varphi,g=\mathbf{id}\))。

  則:

\[S(n)=g(1)S(n)=\displaystyle\sum_{i=1}^{n}(\mathbf{id}\ast\mathbf{id})(i)-\displaystyle\sum_{i=2}^{n}g(i)S\Big(\Big\lfloor\frac{n}{i}\Big\rfloor\Big)=\frac{n(n+1)(2n+1)}{6}-\sum_{i=2}^{n}i\times S\Big(\Big\lfloor\frac{n}{i}\Big\rfloor\Big) \]

程式碼

#include<bits/stdc++.h>
using namespace std;
const int N=2000010;//n^(2/3)
const int mod=1e9+7;
const int inv=166666668;
bool vis[N];
long long n,prime[N+10],phi[N+10],sum[N+10],cnt;
map<long long,long long> mp;
void init()
{
    phi[1]=1;
    for(int i=2;i<=N;i++)
    {
        if(!vis[i])
        {
            prime[++cnt]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=cnt&&i*prime[j]<=N;j++)
        {
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)
            {
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            else
                phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
    }
    for(long long i=1;i<=N;i++)
        sum[i]=(sum[i-1]+i*phi[i]%mod)%mod;
}
long long S(long long n)
{
    if(n<N)
        return sum[n];
    if(mp[n])
        return mp[n];
    long long ans=n*(n+1)%mod*(2*n+1)%mod*inv%mod;
    for(long long l=2,r;l<=n;l=r+1)
    {
        r=n/(n/l);
        ans=((ans-(r*(r+1)/2%mod-(l-1)*l/2%mod)%mod*S(n/l)%mod)%mod+mod)%mod;
    }
    mp[n]=(ans%mod+mod)%mod;
    return ans;
}
int main()
{
    init();
    cin>>n;
    cout<<1<<endl;
    cout<<S(n)<<endl;
    return 0;
}