【bzoj4916】神犇和蒟蒻 杜教筛

Description

很久很久以前,有一只神犇叫yzyrsw;

很久很久之后,有一只蒟蒻叫ltycky;

Input

请你读入一个整数N;1<=N<=1E9,A、B模1E9+7;

Output

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

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

Sample Input

1

Sample Output

1
1

Sol

第一问就是搞笑的,直接puts("1");

第二问其实也不难,只要掌握一个技巧:把约数限制转化成上界限制(莫比乌斯反演大多数都是这样的)

首先根据欧拉函数的定义,\(\varphi(i^2)=\varphi(i)*i\),原因是如果不是新的质因子那么贡献是p,新的质因子贡献是p-1,那么第二个i产生的贡献就全部都是p了,\(\prod{p}=i\)

然后继续推式子:

\(F(n)=\sum_{i=1}^{n}i*\varphi(i)\)

这一步比较神:设\(G(n)=n\),那么F和G的狄利克雷卷积就是\(\sum_{i=1}^{n}\sum_{d|i}\varphi(d)*d*\frac{i}{d}=\sum_{i=1}^{n}i^2=n*(n+1)*(2n+1)/6\)

对于这个卷积式子,我们更换求和指标,消去约数限制,得:

\(\sum_{i=1}^{n}\sum_{d|i}\varphi(d)*d*\frac{i}{d}=\sum_{d=1}^{n}\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}i*\varphi(i)*d\)

如果这一步把后面的i和d弄反了,其实转过来是等价的。

之后原式\(=\sum^{n}_{d=1}d*F(\lfloor\frac{n}{d}\rfloor)\)

\(S(n)=\sum_{i=1}^{n}i^2\),则\(S(n)=\sum_{d=1}^{n}d*F(\lfloor\frac{n}{d}\rfloor)\)

\(S(n)=\sum_{d=2}^{n}d*F(\lfloor\frac{n}{d}\rfloor)+F(n)\)

\(F(n)=S(n)-\sum_{d=2}^{n}d*F(\lfloor\frac{n}{d}\rfloor)\)

杜教筛标准形式。

Code

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n,phi[1000005],pri[1000005],vis[1000005],tot;map<ll,ll>mmp;ll P=6000000042ll,sum[1000005];
ll s1(int l,int r){return 1ll*(l+r)*(r-l+1)%P/2;}
ll s2(int x){return 1ll*x*(x+1)%P*(2*x+1)%P/6;}
ll djs(int x)
{
    if(x<=1000000) return sum[x];
    if(mmp.count(x)) return mmp[x];
    ll ans=s2(x),ls=0;
    for(int i=2;i<=x;i=ls+1) ls=x/(x/i),ans=(ans-1ll*s1(i,ls)*djs(x/i)%P+P)%P;
    mmp[x]=ans;return ans;
}
int main()
{
    phi[1]=sum[1]=1;
    for(int i=2;i<=1000000;i++)
    {
        if(!vis[i]){pri[++tot]=i;phi[i]=i-1;}
        for(int j=1;j<=tot&&i*pri[j]<=1000000;j++)
        {
            vis[i*pri[j]]=1;
            if(i%pri[j]==0){phi[i*pri[j]]=phi[i]*pri[j];break;}
            phi[i*pri[j]]=phi[i]*(pri[j]-1);
        }
        sum[i]=(sum[i-1]+1ll*i*phi[i]%P)%P;
    }
    scanf("%d",&n);printf("1\n%d\n",djs(n)%1000000007);
}

转载于:https://www.cnblogs.com/CK6100LGEV2/p/9398470.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值