设长度为 (n) 字符集大小为 (k) 的回文串的个数为 (g(n)=k^{leftlceilfrac{n}{2} ight ceil}),回文串的每个循环位移都有贡献,但因为循环同构,直接算会算重。不难发现若一个回文串是由同一个串重复循环得到的,那么该串也为回文串,即若有回文串 (s=t^k),则 (t) 也为回文串。考虑枚举回文串的最小循环串长度。
设 (v(n)) 为一个回文串的最小循环串长度为 (n) 时的贡献,(n) 为偶数时会计算两遍,因为当回文串循环位移了 (frac{n}{2}) 后,又会得到一个最小循环串长度为 (n) 的回文串,因此得 (v(n)=nfrac{1+left[ 2 otmid n ight]}{2})。
设 (f(n)) 为最小循环串为其本身的长度为 (n) 的回文串个数,得:
得答案为:
考虑进一步化简 (sumlimits_{dmid frac{n}{t}}muleft(d ight)v(dt)),发现除了 (d) 为偶数且 (t) 为奇数的情况,都有 (v(dt)= dv(t))。考虑 (d) 为偶数且 (t) 为奇数时一定有 (frac{n}{t}) 也为偶数,于是可以将满足 (mu(d) eq 0) 且 (d) 中质因子没有 (2) 的 (d) 和 (2d) 进行配对,因为此时有 (v(dt)=dt=v(2dt)),所以两两配对后得 (sumlimits_{dmid frac{n}{t}}muleft(d ight)v(dt)=0)。
于是就可以代入 (v(dt)= dv(t)),得答案为:
用 (Pollard-Rho) 将 (n) 质因数分解后,用 (dfs) 枚举 (n) 的约数,(dfs) 过程中维护 (prodlimits_{pmid frac{n}{t}}left( 1-p ight)) 即可。
#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
",ans);
}
return 0;
}