【SDOI2018】反回文串
莫比乌斯反演,Pollard_Rho。
题目大意:
给定 $n,k,p$,问有多少个长度为 $n$ 的,字符集大小为 $k$ 的字符串,它是由一个回文串将一个前缀放到后面形成的。答案对 $p$ 取模。
题解:
如果一个回文串由一个子串循环多次得到,那么这个回文串能产生的串就会出现重复。这个子串也一定是个回文串。
具体地,长度为 $n$ 的串由长度为 $m$ 的子串重复得到,则只会产生 $m$ 个本质不同的字符串。
特别地,若 $m$ 为偶数,则循环位移 $\frac m 2$ 位后,会得到另外一个长度为 $n$ 的子串。所以如果 $m$ 为偶数,则只能产生 $\frac m2$ 个本质不同的字符串。
令 $f(m)$ 表示长度为 $n$ 的存在长度为 $m$ 的循环节的回文串个数。$f(m)=k^{\lceil\frac m 2\rceil}$。
令 $g(m)$ 表示长度为 $n$ 的最小循环节为 $m$ 的回文串个数。
可以推出:
莫比乌斯反演得:
令 $h(n)=\frac{n}{1+[n\bmod 2=0]}$。
则:
考虑 $\sum\limits_{m|\frac n d}\mu(m)h(d\cdot m)$。
我们希望它变为:
我们发现,只有当 $d$ 为奇数且 $m$ 为偶数时,$h(d\cdot m)\neq m\cdot h(d)$。
所以 $\frac n d$ 是偶数。
那么后面的式子中,$\mu(m)h(d\cdot m)$ 和 $\mu(2m)h(2\cdot d \cdot m)$($m$ 为奇数)时互为相反数,而当 $m\bmod 4=0$ 时,有$\mu(m)=0$。所以当 $\frac n d$ 为偶数且 $d$ 为奇数时,对答案的贡献为 $0$。
那么:
我们考虑 $\sum\limits_{d|n}\mu(d)\cdot d$ 怎么求。
这个式子相当于把 $d$ 的所有最高次数为 $1$ 的因数拿出来,乘上 $-1$ 的质因子个数次方后加起来。也就是说,
我们用 Pollard_Rho 分解质因数后,进行 dfs,枚举 $\frac n d$ 的值,则后半部分可以在 dfs 中计算出来。
时间复杂度 $O(T(\sqrt{\sqrt n}+d(n)\log n))$。
Code:
#include<cstdio>
#include<vector>
#include<cstdlib>
#include<algorithm>
#include<ctime>
using namespace std;
typedef long long LL;
int T;
LL n,k;int md,ans;
inline LL mul(LL a,LL b,const LL&md){
LL c=a*b-LL((long double)a*b/md+.5)*md;
return(c>>63&md)+c;
}
inline int intpow(int a,LL b){
int ret=1;for(;b;b>>=1,a=(LL)a*a%md)if(b&1)ret=(LL)ret*a%md;return ret;
}
inline LL pow(LL a,LL b,const LL&md){
LL ret=1;for(a%=md;b;b>>=1,a=mul(a,a,md))if(b&1)ret=mul(ret,a,md);return ret;
}
namespace MR{
const int P[]={2,3,5,7,11,13,17,19,23,29,31,37};
bool check(int a,LL n){
LL x=n-1;int d=0;
while(!(x&1))x>>=1,++d;
for(x=pow(a,x,n);d--;){
const LL lst=x;x=mul(x,x,n);
if(x==1&&lst!=1&&lst!=n-1)return 0;
}
return x==1;
}
bool test(LL n){
if(n==1)return 0;
for(int i:P)if(n==i)return 1;
if(!(n&1))return 0;
for(int i:P)if(!check(i,n))return 0;
return 1;
}
}
vector<LL>v;
LL find(LL n,int c){
LL x=rand()%(n-1)+1,y=x,k=2,q=1,t=1;
for(;;k<<=1,y=x,q=1){
for(int i=1;i<=k;++i){
x=mul(x,x,n)+c-n;x+=x>>63&n;
q=mul(q,llabs(x-y),n);
if(!(i&127)){
t=std::__gcd(q,n);
if(t>1)return t;
}
t=std::__gcd(q,n);
if(t>1)return t;
}
}
}
void rho(LL n){
if(n==1)return;
if(MR::test(n))return v.push_back(n);
LL p=n;int c=19260817;
while(p==n)p=find(p,c--);
while(n%p==0)n/=p;
rho(p),rho(n);
}
void dfs(int nw,LL t,int mx){
if(nw==v.size()){
if(t%2==0&&n/t%2==1)return;
t=n/t;
ans=(ans+intpow(k%md,t+1>>1)*((t%2==0?t/2:t)%md)%md*mx)%md;
}else
for(LL x=1;x<=n&&n%x==0;x=(x<=n/v[nw])?x*v[nw]:n+1)
dfs(nw+1,t*x,(x==1)?mx:(mx*(md+1-v[nw]%md)%md));
}
int main(){
srand(time(0));
for(scanf("%d",&T);T--;){
scanf("%lld%lld%d",&n,&k,&md),ans=0,v.clear();
rho(n),sort(v.begin(),v.end()),v.erase(unique(v.begin(),v.end()),v.end());
dfs(0,1,1),printf("%d\n",ans);
}
return 0;
}