傳送門
這裏稍微口胡記錄一下要點,詳細的自己去看xyx的集訓隊論文。
題解:
容易發現我們實際上要算的就是以 爲斜邊的溝谷數的數量。
即統計有多少對 ,滿足 。
我們用高斯整數的角度來看,其實就是求 是多少個高斯整數與其共軛複數的乘積。
在這道題裏面,我們相當於是要對 在高斯整數環中進行質因數分解。
現在我們需要知道一個質數在高斯整數環裏面該如何被分解。
費馬平方和定理:奇質數 可以表示爲兩個正整數 的平方和,當且僅當 ,並且這種表示在 的時候是唯一的。
證明可以直接用高斯整數的理論,見xyx的集訓隊的論文。
2是一個特殊的質數,其分解爲 ,是唯一的。
於是我們考慮 能被表示成多少種不同的高斯整數與其共軛複數的乘積。
不難發現, 的質數可以把分解出的指數任意分配,而其他質數只能對半分。
所以方案數爲
除掉 之後是個積性函數,min_25篩即可。
代碼:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
using std::cerr;
using std::cout;
int mod;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(int a,int b){return a-b<0?a-b+mod:a-b;}
inline int mul(int a,int b){ll r=(ll)a*b;return r>=mod?r%mod:r;}
inline void Inc(int &a,int b){a+=b-mod;a+=a>>31&mod;}
inline void Dec(int &a,int b){a-=b;a+=a>>31&mod;}
inline void Mul(int &a,int b){a=mul(a,b);}
inline int po(int a,ll b){int r=1;for(;b;b>>=1,Mul(a,a))if(b&1)Mul(r,a);return r;}
inline int MD(ll x){return x>=mod?x%mod:x;}
cs int N=1e6+7;
ll n,k;
int pw[100],sp[N];
int c1[2][N],c3[2][N];
int f[2][N];
int p[N],pc;
bool mrk[N];
void linear_sieve(){
for(int re i=2;i<N;++i){
if(!mrk[i])p[++pc]=i;
for(int re j=1;i*p[j]<N;++j){
mrk[i*p[j]]=true;
if(i%p[j]==0)break;
}
}
}
int nn;
void min_25_sieves(){
nn=sqrt(n);
for(int re i=1;i<=nn;++i){
c1[0][i]=(i-1)/4;
c3[0][i]=(i+1)/4;
c1[1][i]=MD((n/i-1)/4);
c3[1][i]=MD((n/i+1)/4);
}int ct1=0,ct3=0;
for(int re j=2;p[j]<=nn;++j){
int p=::p[j],w1=nn/p;
int w2=std::min<ll>(nn,n/p/p);
if((p&3)==1){
for(int re i=1;i<=w1;++i){
Dec(c1[1][i],dec(c1[1][i*p],ct1));
Dec(c3[1][i],dec(c3[1][i*p],ct3));
}for(int re i=w1+1;i<=w2;++i){
Dec(c1[1][i],dec(c1[0][n/i/p],ct1));
Dec(c3[1][i],dec(c3[0][n/i/p],ct3));
}for(int re i=nn;i>=(ll)p*p;--i){
Dec(c1[0][i],dec(c1[0][i/p],ct1));
Dec(c3[0][i],dec(c3[0][i/p],ct3));
}++ct1;
}else {
for(int re i=1;i<=w1;++i){
Dec(c1[1][i],dec(c3[1][i*p],ct3));
Dec(c3[1][i],dec(c1[1][i*p],ct1));
}for(int re i=w1+1;i<=w2;++i){
Dec(c1[1][i],dec(c3[0][n/i/p],ct3));
Dec(c3[1][i],dec(c1[0][n/i/p],ct1));
}for(int re i=nn;i>=(ll)p*p;--i){
Dec(c1[0][i],dec(c3[0][i/p],ct3));
Dec(c3[0][i],dec(c1[0][i/p],ct1));
}++ct3;
}
}for(int re i=1;i<=nn;++i){
f[0][i]=add(c3[0][i],mul(c1[0][i],pw[3]));
f[1][i]=add(c3[1][i],mul(c1[1][i],pw[3]));
}
}
int gf(ll n){
return n<=nn?f[0][n]:f[1][::n/n];
}
int solve(ll n,int i){
int ans=dec(gf(n),f[0][p[i-1]]);if(i==1)++ans;
auto f=[](int p,int t){return (p&3)==1?pw[t<<1|1]:1;};
for(int re j=i;(ll)p[j]*p[j]<=n;++j)
for(ll nw=p[j],t=1;nw*p[j]<=n;nw*=p[j],++t){
Inc(ans,mul(solve(n/nw,j+1),f(p[j],t)));
Inc(ans,f(p[j],t+1));
}
return ans;
}
void Main(){
scanf("%lld%lld%d",&n,&k,&mod);
for(int re i=1;i<=90;++i)pw[i]=po(i,k);
linear_sieve();min_25_sieves();
cout<<mul(pw[4],solve(n,1)+1)<<"\n";
}
inline void file(){
#ifdef zxyoi
freopen("integral.in","r",stdin);
#endif
}signed main(){file();Main();return 0;}