設長度爲 \(n\) 字符集大小爲 \(k\) 的迴文串的個數爲 \(g(n)=k^{\left\lceil\frac{n}{2}\right\rceil}\),迴文串的每一個循環位移都有貢獻,但由於循環同構,直接算會算重。不難發現若一個迴文串是由同一個串重複循環獲得的,那麼該串也爲迴文串,即如有迴文串 \(s=t^k\),則 \(t\) 也爲迴文串。考慮枚舉迴文串的最小循環串長度。c++
設 \(v(n)\) 爲一個迴文串的最小循環串長度爲 \(n\) 時的貢獻,\(n\) 爲偶數時會計算兩遍,由於當迴文串循環位移了 \(\frac{n}{2}\) 後,又會獲得一個最小循環串長度爲 \(n\) 的迴文串,所以得 \(v(n)=n\frac{1+\left[ 2 \not\mid n \right]}{2}\)。git
設 \(f(n)\) 爲最小循環串爲其自己的長度爲 \(n\) 的迴文串個數,得:spa
得答案爲:code
考慮進一步化簡 \(\sum\limits_{d\mid \frac{n}{t}}\mu\left(d\right)v(dt)\),發現除了 \(d\) 爲偶數且 \(t\) 爲奇數的狀況,都有 \(v(dt)= dv(t)\)。考慮 \(d\) 爲偶數且 \(t\) 爲奇數時必定有 \(\frac{n}{t}\) 也爲偶數,因而能夠將知足 \(\mu(d)\neq 0\) 且 \(d\) 中質因子沒有 \(2\) 的 \(d\) 和 \(2d\) 進行配對,由於此時有 \(v(dt)=dt=v(2dt)\),因此兩兩配對後得 \(\sum\limits_{d\mid \frac{n}{t}}\mu\left(d\right)v(dt)=0\)。get
因而就能夠代入 \(v(dt)= dv(t)\),得答案爲:it
用 \(Pollard-Rho\) 將 \(n\) 質因數分解後,用 \(dfs\) 枚舉 \(n\) 的約數,\(dfs\) 過程當中維護 \(\prod\limits_{p\mid \frac{n}{t}}\left( 1-p \right)\) 便可。class
#include<bits/stdc++.h> #define maxn 110 using namespace std; typedef long long ll; template<typename T> inline void read(T &x) { x=0;char c=getchar();bool flag=false; while(!isdigit(c)){if(c=='-')flag=true;c=getchar();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();} if(flag)x=-x; } ll T,n,k,p,cnt,tot,ans; ll pri[12]={2,3,5,7,11,13,17,19},t[maxn],v[maxn],a[maxn]; ll mul(ll x,ll y,ll mod) { ll c=(long double)x*y/mod+0.5; c=x*y-c*mod; return c<0?c+mod:c; } ll qp(ll x,ll y,ll mod) { ll v=1; while(y) { if(y&1) v=mul(v,x,mod); x=mul(x,x,mod),y>>=1; } return v%mod; } bool check(ll x,ll p,ll mod) { ll t=qp(x,p,mod); if(t==mod-1) return true; if(t==1) return p&1?true:check(x,p/2,mod); return false; } bool Miller_Rabin(ll n) { if(n==1) return false; if(n<=3) return true; if(!(n&1)) false; for(int i=0;i<8;++i) { if(n==pri[i]) return true; if(!check(pri[i],n-1,n)) return false; } return true; } ll gcd(ll a,ll b) { return b?gcd(b,a%b):a; } ll f(ll x,ll y,ll mod) { return (mul(x,x,mod)+y)%mod; } ll Pollard_Rho(ll x) { ll s=0,t=0,c=(ll)rand()%(x-1)+1,val=1; for(ll goal=1;;goal<<=1,s=t,val=1) { for(ll step=1;step<=goal;++step) { t=f(t,c,x); val=mul(val,abs(t-s),x); if(step%127==0) { ll d=gcd(val,x); if(d>1) return d; } } ll d=gcd(val,x); if(d>1) return d; } } void fac(ll x) { if(x<2) return; if(Miller_Rabin(x)) { t[++cnt]=x; return; } ll p=x; while(p>=x) p=Pollard_Rho(x); fac(x/p),fac(p); } void dfs(int x,ll d,ll t) { if(x==tot+1) { if(!(n/d&1)||(d&1)) ans=(ans+qp(k,(n/d+1)/2,p)*(((n/d&1)?n/d:n/d/2)%p)%p*t%p)%p; return; } dfs(x+1,d,t),t=t*(1-v[x]%p+p)%p; for(int i=1;i<=a[x];++i) d*=v[x],dfs(x+1,d,t); } int main() { srand((ll)new char),read(T); while(T--) { read(n),read(k),read(p),k%=p,cnt=tot=ans=0; fac(n),sort(t+1,t+cnt+1); for(int i=1;i<=cnt;++i) { if(t[i]!=t[i-1]) v[++tot]=t[i],a[tot]=0; a[tot]++; } dfs(1,1,1),printf("%lld\n",ans); } return 0; }