【GDOI2018模拟8.11】质数

来源:互联网 发布:黑色沙漠游侠捏脸数据 编辑:程序博客网 时间:2024/06/06 10:48

Description

i=1n2f(i)

f(i)表示i的不同的质因子个数
n<=10^12

Solution

我们设g(i)=2^f(i),显然g是积性函数
那么我们可以尝试杜教筛g
把g卷上一个mu,设g*mu=h
显然h也是积性函数
分析一下h(p^k),我们可以发现h(p^k)=[k==1]
特别的h[1]=1
那么归纳一下我们可以发现h=mu^2!!
也就是g*mu=mu^2
两边再卷上一个I,那么g=mu^2*I
说人话就是g(n)=d|nmu(i)2
这样是可以杜教筛的,但是由于出题人很不良心这样会被卡成暴力分
我们需要一个更优秀的解法
先把原式子写出来

Ans=i=1nd|iμ(d)2

枚举j=i/d,
Ans=j=1nd=1nj2μ(d)2

考虑ni=1μ(d)2要怎么求
如果存在一个p^2|d那么mu(d)^2=0否则mu(d)^2=1
如果我们考虑容斥,枚举一个p^2把答案减去n/(p^2)
但这样会算重所有我们要加上n/(p*p’)^2
可以发现容斥系数相当于mu
所以
i=1nμ(d)2=i=1nμ(i)ni2

Ans=j=1nd=1nj2μ(d)nd2j
Ans=d=1nμ(d)j=1nd2nd2j

后面可以分块,复杂度O(nlogn13)

Code

#include <cmath>#include <cstdio>#include <cstring>#include <algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)using namespace std;typedef long long ll;const int N=1e6+5,mo=998244353;int p[N],mu[N];bool bz[N];ll n,ans;void prepare(int n) {    mu[1]=1;    fo(i,2,n) {        if (!bz[i]) p[++p[0]]=i,mu[i]=-1;        fo(j,1,p[0]) {            int k=i*p[j];if (k>n) break;            bz[k]=1;if (!(i%p[j])) break;            mu[k]=-mu[i];        }    }}int main() {    scanf("%lld",&n);    int m=sqrt(n);    prepare(m);    fo(i,1,m) {        if (!mu[i]) continue;        int sum=0;ll nn=n/i/i;        for(ll l=1,r;l<=nn;l=r+1) {            r=nn/(nn/l);            (sum+=(ll)(r-l+1)*(nn/l)%mo)%=mo;        }        if (mu[i]==1) (ans+=sum)%=mo;        else (ans+=mo-sum)%=mo;    }    printf("%d\n",ans);}
原创粉丝点击