luoguP1659 [国际集训队]拉拉队排练 manacher算法

直接统计长度为$i$的回文子串有多少个

然后倒叙枚举长度,快速幂统计一下即可

复杂度$O(n log n)$

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define ll long long
#define ri register int
#define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
#define drep(io, ed, st) for(ri io = ed; io >= st; io --)
    
const int sid = 1000005;
const int mod = 19930726;

inline void inc(int &a, int b) { a += b; if(a >= mod) a -= mod; }
inline void dec(int &a, int b) { a -= b; if(a < 0) a += mod; }
inline int mul(int a, int b) { return 1ll * a * b % mod; }
inline int fp(int a, int k) {
    int ret = 1;
    for( ; k; k >>= 1, a = mul(a, a))
        if(k & 1) ret = mul(ret , a);
    return ret;
}

ll n, k;
char s[sid];
int r[sid], num[sid];

int main() {
    cin >> n >> k;
    scanf("%s", s + 1);
    int mr = 1, pos = 1; r[1] = 1;
    rep(i, 2, n) {
        r[i] = min(mr - i + 1, r[pos + pos - i]);
        while(i - r[i] > 0 && s[i + r[i]] == s[i - r[i]]) r[i] ++;
        if(i + r[i] - 1 > mr) mr = i + r[i] - 1, pos = i;
    }
    rep(i, 1, n) num[2 * r[i] - 1] ++;
    drep(i, n, 1) num[i] += num[i + 1];
    
    int ans = 1;
    drep(i, n, 1)
    if(i & 1) {
        if(k >= num[i]) {
            ans = mul(ans, fp(i, num[i]));
            k -= num[i];
        }
        else {
            ans = mul(ans, fp(i, k));
            break;
        }
    }
    
    printf("%d
", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/reverymoon/p/9964680.html