洛谷P4607 [SDOI2018] 反迴文串

設長度爲 \(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

\[\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} \]

得答案爲:code

\[\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\)get

因而就能夠代入 \(v(dt)= dv(t)\),得答案爲:it

\[\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)\) 便可。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;
}
相關文章
相關標籤/搜索