E2. Beautiful Patterns (Hard Version)

传送门

首先结论:对于两个子数组,若他们回文中心不重合,则他们各自为回文串这两件事互相独立。

一个子数组回文,设该子数组长为\(len\),即相当于对这个子数组产生$ \left \lfloor \frac{len}{2}\right \rfloor$个约束:

\(a_{l}=a_{r},a_{l+1}=a_{r-1},...\)

若两子数组回文中心不重合,则对于两个子数组产生的约束一定不会出现重复,故而两者同时发生的概率等于所有约束同时发生的概率,也即两个子数组各自的约束发生概率的乘积

而如果出现回文中心重合,则会出现约束的重复,此时两者同时回文的概率等于较长子数组回文的概率。

\(x_{l,r}\)表示区间 $[l,r] $ 回文的概率

要求\(E(\sum^2x_{l,r})\)

\(E(\sum^2x_{l,r}) = E(\sum x_{l,r} \sum x_{l,r})=E(\sum \sum x_{l_{1},r_{1}}x_{l_{2},r_{2}})\)

即变成求任两个区间同时回文的概率总和。

首先求出任意区间回文的概率总和\(P\)

首先规定\(si_{i}\)表示\(\frac{1}{m^i}\)\(sm_{i}\)表示\(\sum_{0}^{i} si_{l}\)

那么对于求\(P\),首先对于每一个以当前位置为回文中心的情况,对当前位置首先算约束个数\(L=min(i-1,n-i)\)

那么将\(sm_{L}\)贡献到\(P\)

其次对于以当前位置到下一个位置之间为回文中心的情况,约束个数\(L=min(i,n-i)\)

则将\(\sum_{1}^{L} si_{i}\),即\(sm_{L}-1\)贡献到\(P\)

算出\(P\)后,利用\(P\)算每个回文中心对答案的贡献。对于以某个下标作为回文中心的情况,利用以下容斥,设\(L=min(i - 1,n - i)\),则贡献为:

\(\sum_{0}^{L}si_{i}*(P-sm_{L})+sm_{L}-sm_{i}+(i+1)*si_{i}\)

而两位置之间作为回文中心的情况是类似的,这时候产生的新量也需要提前预处理。

代码:

void solve() {
    cin >> n >> m >> mod;
    Z::setMod(mod);
    vector<Z> si(n + 10),sm(n + 10);
    vector<Z> s1(n + 10),s2(n + 10),s3(n + 10),ss(n + 10);
    si[0] = 1;
    for(int i = 1;i <= n;i++) si[i] = si[i - 1] / m;
    sm[0] = 1;
    for(int i = 1;i <= n;i++) sm[i] = sm[i - 1] + si[i];
    s1[0] = 1;
    s2[0] = 1; 
    for(int i = 1;i <= n;i++) {
        s1[i] = s1[i - 1] + sm[i];
        s2[i] = s2[i - 1] + (i + 1) * si[i];
        s3[i] = s3[i - 1] + i * si[i];
        ss[i] = ss[i - 1] + si[i];
    }
    for(int i = 1;i <= n;i++) ss[i] = ss[i - 1] + ss[i];
    Z P = 0;
    for(int i = 1;i <= n;i++) {
        int L = min(i - 1,n - i);
        P += sm[L];
        if(i < n) {
            L = min(i,n - i);
            P += sm[L] - 1;
        }
    }
    Z ans = 0;
    for(int i = 1;i <= n;i++) {
        int L = min(i - 1,n - i);
        ans += sm[L] * (P - sm[L]) + (L + 1) * sm[L] - s1[L] + s2[L];
        if(i < n) {
            L = min(i,n - i);
            ans += (sm[L] - 1) * (P - sm[L] + 1) + L * (sm[L] - 1) - ss[L] + s3[L];
        }
    }
    cout << ans << '\n';
}
posted @ 2026-01-30 18:47  孤枕  阅读(0)  评论(0)    收藏  举报