【BZOJ4916】神犇和蒟蒻 解题报告

【BZOJ4916】神犇和蒟蒻

Description

很久很久以前,有一群神犇叫sk和ypl和ssr和hjh和hgr和gjs和yay和xj和zwl和dcx和lyy和dtz和hy和xfz和myh和yww和zjt;

很久很久之后,有一只蒟蒻叫ypl,被神犇myh的做题记录碾在地上;

Input

​ 请你读入一个整\(N\);

Output

​ 请你输出一个整数\(A=\sum_{i=1}^n\mu(i^2);(\bmod1000000007)\)

​ 请你输出一个整数\(B=\sum_{i=1}^n\varphi(i^2);(\bmod 1000000007)\)

HINT

\(1≤N≤10^9\)


杜教筛板子,复习了一下...

显然\(A=1\)

然后\(\varphi(i^2)=i\varphi(i)\),因为不改变质因子的种类,所以可以直接乘出来。

\(\mathtt f=i\varphi(i)\),那么

\[\mathtt {Id^2}=\mathtt f * \mathtt{Id} \]

于是直接杜教筛就行了


Code:

#include <cstdio>
#include <unordered_map>
#define ll long long
std::unordered_map <int,ll> F;
const int N=1e6;
const ll mod=1e9+7;
int pri[N+10],ispri[N+10],cnt;
ll f[N+10];
void init()
{
    f[1]=1;
    for(int i=2;i<=N;i++)
    {
        if(!ispri[i])
        {
            pri[++cnt]=i;
            f[i]=i-1;
        }
        for(int j=1;j<=cnt&&pri[j]*i<=N;j++)
        {
            ispri[i*pri[j]]=1;
            if(i%pri[j]==0)
            {
                f[i*pri[j]]=f[i]*pri[j];
                break;
            }
            f[i*pri[j]]=f[i]*(pri[j]-1);
        }
    }
    for(int i=1;i<=N;i++) f[i]=(f[i]*i+f[i-1])%mod;
}
#define g(a) (1ll*(a)*(a+1)/2)
const ll inv=166666668;
ll Sum(int n)
{
    if(n<=N) return f[n];
    if(F.find(n)!=F.end()) return F[n];
    ll ret=1ll*n*(n<<1|1)%mod*(n+1)%mod*inv%mod;
    for(int l=2,r;l<=n;l=r+1)
    {
        r=n/(n/l);
        (ret-=(g(r)-g(l-1))*Sum(n/l))%=mod;
    }
    return F[n]=((ret+mod)%mod);
}
int main()
{
    init();
    int n;scanf("%d",&n);
    printf("1\n%lld",Sum(n));
    return 0;
}

2018.12.16

posted @ 2018-12-16 09:14  露迭月  阅读(175)  评论(0编辑  收藏  举报