P3768 简单的数学题(莫反+杜教筛)
题面
一点也不简单。
思路:
设
时间复杂度
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,p,phi[3000005],sum[3000005],prime[3000005],inv2,inv6,tot;
bool vis[3000005];
unordered_map<int,int> q;
int qpow(int x,int y,int mod){
int ans=1;
while(y){if(y&1) ans=ans*x%mod;x=x*x%mod,y>>=1;}
return ans;
}
int sum1(int x){x%=p;return x*(x+1)%p*inv2%p;}
int sum2(int x){x%=p;return x*(x+1)%p*(2*x+1)%p*inv6%p;}
int sum3(int x){x%=p;return sum1(x)*sum1(x)%p;}
void euler(){
phi[1]=1;
for(int i=2;i<=3000000;i++){
if(!vis[i]) vis[i]=1,phi[i]=i-1,prime[++tot]=i;
for(int j=1;j<=tot&&i*prime[j]<=3000000;j++){
vis[i*prime[j]]=1;
if(i%prime[j]==0){phi[i*prime[j]]=phi[i]*prime[j];break;}
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
for(int i=1;i<=3000000;i++) sum[i]=(sum[i-1]+phi[i]*i%p*i%p)%p;
}
int calc(int x){
if(x<=3000000) return sum[x];
if(q.find(x)!=q.end()) return q[x];
int s=sum3(x);
for(int l=2,r,t;l<=x;l=r+1){
t=x/l,r=x/t;
s=((s-calc(t)*((sum2(r)-sum2(l-1))%p+p)%p)%p+p)%p;
}
return q[x]=s;
}
signed main(){
cin>>p>>n;euler();inv2=qpow(2,p-2,p),inv6=qpow(6,p-2,p);int ans=0;
for(int l=1,r,t;l<=n;l=r+1) t=n/l,r=n/t,ans=(ans+(sum3(t)*(((calc(r)-calc(l-1))%p+p)%p))%p)%p;
cout<<ans<<endl;
return 0;
}