@xiaoziyao
2020-05-04T12:39:00.000000Z
字数 4845
阅读 1161
解题报告
简单的数学题解题报告:
题意:求
数据范围:且,保证为质数
做这道题前,请保证你已经学会莫比乌斯反演和杜教筛0,否则可以到我博珂里康康:
狄利克雷卷积&莫比乌斯反演学习笔记
杜教筛学习笔记
开始推式子:
代码:
#include<stdio.h>
#include<map>
using namespace std;
const long long maxn=5000005;
long long i,j,k,m,n,mod,cnt,inv6;
long long a[maxn],p[maxn],varphi[maxn],S[maxn];
map<long long,long long>ans;
inline long long getsum(long long n){
return n*(n+1)/2%mod;
}
inline long long calc(long long n){
return n*(n+1)%mod*(2*n+1)%mod*inv6%mod;
}
long long ksm(long long a,long long b,long long mod){
long long res=1;
while(b){
if(b&1)
res=(res*a)%mod;
a=(a*a)%mod,b>>=1;
}
return res;
}
long long getS(long long n){
if(n<maxn)
return S[n];
if(ans.count(n))
return ans[n];
long long l=2,r,res=getsum(n)*getsum(n)%mod;
while(l<=n){
r=n/(n/l);
res=((res-(calc(r)-calc(l-1)+mod)%mod*getS(n/l)%mod)%mod+mod)%mod;
l=r+1;
}
res=(res%mod+mod)%mod;
return ans[n]=res;
}
long long getans(long long n){
long long l=1,r,res=0;
while(l<=n){
r=n/(n/l);
res=(res+(getS(r)-getS(l-1)+mod)%mod*getsum(n/l)%mod*getsum(n/l)%mod)%mod;
l=r+1;
}
res=(res%mod+mod)%mod;
return res;
}
int main(){
scanf("%lld%lld",&mod,&n);
inv6=ksm(6,mod-2,mod);
p[1]=varphi[1]=1;
for(i=2;i<maxn;i++){
if(p[i]==0)
a[++cnt]=i,varphi[i]=i-1;
for(j=1;j<=cnt;j++){
if(i*a[j]>=maxn)
break;
p[i*a[j]]=1;
if(i%a[j]==0){
varphi[i*a[j]]=varphi[i]*a[j];
break;
}
varphi[i*a[j]]=varphi[i]*(a[j]-1);
}
}
for(i=1;i<maxn;i++)
S[i]=(S[i-1]+varphi[i]%mod*i%mod*i%mod)%mod;
printf("%lld\n",getans(n));
return 0;
}