命運的X

彬彬冰激凌發表於2024-10-30

命運的X

cjx 生成函式強。

思路

首先,設 \(f_i\) 為新增第 \(i\) 項後滿足條件的機率,\(g_i\) 任意新增至第 \(i\) 項的機率。

我們要求的答案:

\[ans=\sum_{i=0} i\times f_i \]

我們把 \(f\) 放入生成函式中:

\[F=\sum_{i=0} f_i x^i \]

顯然有 \(F(1)=1\)

\(F\) 進行取導。

\[F'=\sum_{i=1} i\times f_ix^{i-1} \]

發現有 \(ans=F'(1)\)

\(g\) 也用生成函式 \(G\) 表示出來。

考慮加入一個字元,那麼有 \(xG=G+F\),即可能匹配,也可能不匹配。

移項得,\((x-1)G=F\)

導一下,\(G+(x-1)G'=F'\)

\(x=1\),得 \(G(1)=F'(1)\)

考慮對 \(G\) 做轉移,每次向後新增一段 \(b\)。當然可能新增中途已經存在最後一段等於 \(b\) 的情況,我們也要考慮,那就有:

\[\frac{x^n}{m^n}G=\sum_{i=1}^n[i]F\cdot \frac{x^{n-i}}{m^{n-i}} \]

其中 \(i\) 滿足,\(b[1,i]=b[n-i+1,n]\)

移項得:

\[G=\sum_{i=1}^n [i] F\cdot \frac{m^i}{x^i} \]

\(x=1\),對下式求和即可。

\[ans=G(1)=\sum_{i=1}^n[i]F(1)\cdot m^i \]

CODE

#include<bits/stdc++.h>
using namespace std;

#define ll long long
#define N 200000
#define pll pair<ll,ll>

const int maxn=2e5+5;
const ll mod=998244353,base=20090327,mod1=1e9+7,mod2=1e9+9;

int n,m;
int b[maxn];

ll pw1[maxn],pw2[maxn],sum1[maxn],sum2[maxn];

inline void init()
{
    pw1[0]=pw2[0]=1;
    for(int i=1;i<=N;i++)
        pw1[i]=pw1[i-1]*base%mod1,
        pw2[i]=pw2[i-1]*base%mod2;
}

inline pll calc(int l,int r){return {(sum1[r]-sum1[l-1]*pw1[r-l+1]%mod1+mod1)%mod1,(sum2[r]-sum2[l-1]*pw2[r-l+1]%mod2+mod2)%mod2};}
inline void solve()
{
    ll tmp=1,ans=0;
    for(int i=1;i<=n;i++)
    {
        tmp=tmp*m%mod;
        if(calc(1,i)==calc(n-i+1,n)) ans=(ans+tmp)%mod;
    }
    printf("%lld\n",ans);
}

int main()
{
    freopen("x.in","r",stdin);
    freopen("x.out","w",stdout);
    int _;
    init();
    scanf("%d",&_);
    while(_--)
    {
        memset(sum1,0,sizeof(sum1));
        memset(sum2,0,sizeof(sum2));
        scanf("%d%d",&m,&n);
        for(int i=1;i<=n;i++) scanf("%d",&b[i]);
        for(int i=1;i<=n;i++)
            sum1[i]=(sum1[i-1]*base+b[i]%mod1)%mod1,
            sum2[i]=(sum2[i-1]*base+b[i]%mod2)%mod2;
        solve();
    }
}

相關文章