洛谷P4607 [SDOI2018] 反回文串

设长度为 \(n\) 字符集大小为 \(k\) 的回文串的个数为 \(g(n)=k^{\left\lceil\frac{n}{2}\right\rceil}\),回文串的每个循环位移都有贡献,但因为循环同构,直接算会算重。不难发现若一个回文串是由同一个串重复循环得到的,那么该串也为回文串,即若有回文串 \(s=t^k\),则 \(t\) 也为回文串。考虑枚举回文串的最小循环串长度。

\(v(n)\) 为一个回文串的最小循环串长度为 \(n\) 时的贡献,\(n\) 为偶数时会计算两遍,因为当回文串循环位移了 \(\frac{n}{2}\) 后,又会得到一个最小循环串长度为 \(n\) 的回文串,因此得 \(v(n)=n\frac{1+\left[ 2 \not\mid n \right]}{2}\)

\(f(n)\) 为最小循环串为其本身的长度为 \(n\) 的回文串个数,得:

\[\large\begin{aligned} \sum_{d\mid n} f(d)&=g(n)\\ f(n)&=\sum_{d\mid n}g(d)\mu\left(\frac{n}{d}\right)\\ \end{aligned} \]

得答案为:

\[\large\begin{aligned} &\sum_{d\mid n} f(d)v(d)\\ =&\sum_{d\mid n}\sum_{t\mid d}g(t)\mu\left(\frac{d}{t}\right)v(d)\\ =&\sum_{t\mid n}g(t)\sum_{d\mid \frac{n}{t}}\mu\left(d\right)v(dt)\\ \end{aligned} \]

考虑进一步化简 \(\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\)

于是就可以代入 \(v(dt)= dv(t)\),得答案为:

\[\large\begin{aligned} &\sum_{t\mid n}g(t)v(t)\sum_{d\mid \frac{n}{t}}\mu\left(d\right)d\\ =&\sum_{t\mid n}g(t)v(t)\prod_{p\mid \frac{n}{t}}\left( 1-p \right) \end{aligned} \]

\(Pollard-Rho\)\(n\) 质因数分解后,用 \(dfs\) 枚举 \(n\) 的约数,\(dfs\) 过程中维护 \(\prod\limits_{p\mid \frac{n}{t}}\left( 1-p \right)\) 即可。

#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;
}
posted @ 2021-01-27 12:43  lhm_liu  阅读(208)  评论(0编辑  收藏  举报