习题:神犇和蒟蒻(杜教筛)

题目

传送门

思路

对于A而言。。。。显然A=1

\[设n=\prod p_i^{a_i}\\\varphi(n)=\prod \varphi(p_i^{a_i})\\\varphi(n^2)=\prod\varphi(p_i^{2a_i})\\考虑到\varphi之中全部都是质数,\\\varphi(p^a)=p^a-p^{a-1}\\\varphi(p^{2a})=p^{2a}-p^{2a-1}=p^a(p^a-p^{a-1})\\\varphi(n^2)=\prod p^a\varphi(p^a)\\\varphi(n^2)=n\varphi(n) \]

\[设f(i)=\varphi(i^2)=i\varphi(i),F(i)=\sum_{i=1}^{n}f(i)\\设g(i)=i,G(i)=\sum_{i=1}^ng(i)\\那么h(i)=(f*g)(i)=i^2 \]

\[那么根据杜教筛的结论,有\\F(n)=\frac{H(n)-\sum_{d=2}^ng(i)F(\lfloor\frac{n}{d}\rfloor)}{g(1)} \]

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

代码

#include<unordered_map>
#include<iostream>
using namespace std;
const int mod=1e9+7;
const int inv6=166666668;
const int inv2=500000004;
int n;
unordered_map<int,int> mf;
long long f[10000005];
long long summ(int n)
{
    return 1ll*n*(n+1)%mod*inv2%mod;
}
long long getphi(int n)
{
    if(n<=10000000&&f[n])
        return f[n];
    if(mf.count(n))
        return mf[n];
    long long temp=1ll*n*(n+1)%mod*(2*n+1)%mod*inv6%mod;
    for(int l=2,r;l<=n;l=r+1)
    {
        r=min(n/(n/l),n);
        temp=(temp-(summ(r)-summ(l-1))*getphi(n/l))%mod;
    }
    temp=(temp%mod+mod)%mod;
    if(n<=10000000)
        return f[n]=temp;
    else
        return mf[n]=temp;
}
int main()
{
    cin>>n;
    cout<<1<<'\n'<<getphi(n);
    return 0;
}
posted @ 2021-01-31 16:06  loney_s  阅读(77)  评论(0)    收藏  举报