「luogu3768」简单的数学题
莫比乌斯函数+杜教筛
注意n*n就会爆long long 写程序时要格外小心。
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N=5000010; 5 int lim=5000000,p[N],tot; 6 ll n,sum[N],inv2,inv6,mod,phi[N]; 7 map<ll,ll>hs; 8 bool isp[N]; 9 ll qpow(ll x,ll y){ 10 ll res=1; 11 while(y){ 12 if(y&1) res=res*x%mod; 13 x=x*x%mod,y>>=1; 14 } 15 return res; 16 } 17 void pre(){ 18 phi[1]=1; 19 for(int i=2;i<=lim;i++){ 20 if(!isp[i]) p[++tot]=i,phi[i]=(i-1)%mod; 21 for(int j=1;j<=tot&&1LL*i*p[j]<=lim;j++){ 22 isp[i*p[j]]=1; 23 if(i%p[j]) phi[i*p[j]]=phi[i]*(p[j]-1)%mod; 24 else{phi[i*p[j]]=phi[i]*p[j]%mod;break;} 25 } 26 } 27 for(int i=1;i<=lim;i++) sum[i]=(sum[i-1]+phi[i]*i%mod*i)%mod; 28 return; 29 } 30 inline ll calc(ll k){ 31 k%=mod; 32 return k*(k+1)%mod*(2*k+1)%mod*inv6%mod; 33 } 34 ll getsum(ll k){ 35 if(k<=lim) return sum[k]; 36 if(hs[k]) return hs[k]; 37 ll l=2,r,temp=(k+1)%mod*k%mod*inv2%mod,res=temp*temp%mod; 38 while(l<=k){ 39 r=k/(k/l); 40 res=((res-(calc(r)-calc(l-1))%mod*getsum(k/l)%mod)%mod+mod)%mod; 41 l=r+1; 42 } 43 return hs[k]=res; 44 } 45 int main(){ 46 scanf("%lld%lld",&mod,&n); 47 pre(); 48 inv6=qpow(6,mod-2),inv2=qpow(2,mod-2); 49 ll l=1,r,ans=0; 50 while(l<=n){ 51 r=n/(n/l); 52 ll temp=(n/l%mod)*(n/l%mod+1)%mod*inv2%mod; 53 ans=((ans+temp*temp%mod*((getsum(r)-getsum(l-1))%mod+mod)%mod)%mod+mod)%mod; 54 l=r+1; 55 } 56 ans=(ans+mod)%mod; 57 printf("%lld",ans); 58 return 0; 59 }