LOJ6053简单的函数(min_25筛)

LOJ6053简单的函数

https://loj.ac/p/6053
min_25筛模板题,但是要注意质数点有2比较特殊,需要在y==0的时候特判质数包含2的情况。

#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline LL read()
{
	char x='\0';
	LL fh=1,sum=0;
	for(x=getchar();x<'0'||x>'9';x=getchar())if(x=='-')fh=-1;
	for(;x>='0'&&x<='9';x=getchar())sum=sum*10+x-'0';
	return fh*sum;
}
const LL N=1000009;
const LL mod=1e9+7;
LL n,sq;
LL pri[N],pcnt,sp[N];
bool vis[N];
inline void init(int mx) 
{
	vis[0]=vis[1]=true;
	for(LL i=2;i<=mx;i++)
	{
		if(!vis[i])pri[++pcnt]=i,sp[pcnt]=(sp[pcnt-1]+i)%mod;
		for(int j=1;j<=pcnt&&i*pri[j]<=mx;j++)
		{
			vis[i*pri[j]]=true;
			if(i%pri[j]==0)break;
		}
	}
}
LL w[N],tot,ind1[N],ind2[N],g1[N],g0[N];
inline LL S(LL x,int y)
{
	if(x<=1||pri[y]>=x)return 0;
	LL k=(x<=sq)?ind1[x]:ind2[n/x];
	LL ans=g1[k]-g0[k]-(sp[y]-y);
	if(y==0)ans+=2;
	for(int i=y+1;i<=pcnt&&pri[i]*pri[i]<=x;i++)
	{
		for(LL j=1,pe=pri[i];pe<=x;j++,pe*=pri[i])
		{
			ans=(ans+(pri[i]^j)*(S(x/pe,i)+(j!=1))%mod)%mod;
		}
	}
	return ans;
}
int main()
{
	n=read();
	sq=sqrt(n);
	init(sq);
	for(LL lp=1,rp=0;lp<=n;lp=rp+1)
	{
		rp=n/(n/lp);
		w[++tot]=n/lp;
		if(w[tot]<=sq)ind1[w[tot]]=tot;
		else ind2[n/w[tot]]=tot;
		LL now=w[tot]%mod;
		g1[tot]=(now*(now+1)/2%mod-1+mod)%mod;
		g0[tot]=(now-1+mod)%mod;
	}
//	cout<<g1[1]<<endl;//
	for(int i=1;i<=pcnt;i++)
	{
		for(int j=1;j<=tot&&pri[i]*pri[i]<=w[j];j++)
		{
			LL now=w[j]/pri[i];
			LL k=(now<=sq)?ind1[now]:ind2[n/now];
			g1[j]=(g1[j]-pri[i]*(g1[k]-sp[i-1])%mod+mod)%mod;
			g0[j]=(g0[j]-(g0[k]-(i-1))+mod)%mod;
		}
	}
//	cout<<g1[1]<<' '<<g0[1]<<endl;//
	printf("%lld",(S(n,0)+1)%mod);
	return 0;
}

posted @ 2021-01-16 16:16  dinlon  阅读(32)  评论(0)    收藏  举报