题面
式子还是很好推的,显然应该设g[i]=i,和欧拉函数求和是一样的道理,想要把前面的i给抵消掉
注意!取模! 不然会爆long long
然后一开始的素数取到n^(2/3)是最好的
#include<bits/stdc++.h> #define mod 1000000007 #define LL long long using namespace std; LL read() { LL x=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x*f; } int prime[1000000],notp[6000001],mu[6000001]; LL tot=0; map<LL,LL>w; LL ans[6000003]; void init(LL n) { mu[1]=1; for(LL i=2;i<=n;++i) { if(!notp[i]) { prime[++tot]=i; mu[i]=-1; } for(LL j=1;j<=tot&&i*prime[j]<=n;++j) { notp[i*prime[j]]=1; if(i%prime[j]==0){mu[i*prime[j]]=0;break;} else mu[i*prime[j]]=-mu[i]; } } for(int i=1;i<=n;++i)ans[i]=(ans[i-1]+mu[i]*i%mod)%mod; } LL djs(LL x) { if(x<=6000000)return ans[x]; if(w[x])return w[x]%mod; LL res=1; for(LL l=2,r;l&&l<=x;l=r+1) { r=x/(x/l); LL g=(((l+r)%mod*(r-l+1)%mod)%mod*500000004%mod)%mod;//g[i]=i首项加末项乘项数除以2 res=(res+mod-(g%mod*djs(x/l))%mod)%mod;//取mod一定要注意!不然会爆long long } return w[x]=res%mod; } int main() { freopen("b.in","r",stdin); freopen("b.out","w",stdout); LL n=read(); //ans[n]=∑(n)h[i]-∑(n)*ans[n/i] init(6000000); printf("%lld ",djs(n)); }