n<=10000000000
然后欧拉函数的前缀和可以用莫比乌斯函数的前缀和快速求,注意各种取模
#include<cstdio> typedef long long i64; const int N=20000000,P=1844677,M=1000000007,I2=(M+1)/2; int ps[N/5],pp=0; bool isnp[N+5]; int ms[N+5],phs[N+5]; i64 xs[P]; int ys[P]; int f(i64 n){ if(n<=N)return ms[n]; int w=n%P; while(xs[w]){ if(xs[w]==n)return ys[w]; w+=1237; if(w>=P)w-=P; } xs[w]=n; i64 s=0; for(i64 i=2,j;i<=n;i=j+1){ j=n/(n/i); s+=(j-i+1)*f(n/i); } return ys[w]=1-s; } int sum_phi(i64 n){ if(n<=N)return phs[n]; i64 ans=0; for(i64 i=1,j;i<=n;i=j+1){ i64 k=n/i; j=n/k; k%=M; ans=(ans+k*k%M*(f(j)-f(i-1)))%M; } ans=(ans+1)*I2%M; return ans; } int main(){ ms[1]=phs[1]=1; for(int i=2;i<=N;i++){ if(!isnp[i])ms[ps[pp++]=i]=-1,phs[i]=i-1; for(int j=0;j<pp&&i*ps[j]<=N;j++){ isnp[i*ps[j]]=1; if(i%ps[j])ms[i*ps[j]]=-ms[i],phs[i*ps[j]]=phs[i]*(ps[j]-1); else{ phs[i*ps[j]]=phs[i]*ps[j]; break; } } } for(int i=1;i<=N;i++)ms[i]+=ms[i-1]; for(int i=1;i<=N;i++)(phs[i]+=phs[i-1])%=M; i64 n,ans=0; scanf("%lld",&n); for(i64 i=1,j=1,k;i<=n;i=j+1){ k=n/i; j=n/k; k%=M; ans=(ans+k*(k+1)%M*(sum_phi(j)-sum_phi(i-1)))%M; } n%=M; ans=(ans-n*(n+1)%M*I2)%M; printf("%lld",(ans+M)%M); return 0; }
时间: 2024-10-20 14:17:33