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\n", ans); return 0; }
喵喵喵?喵喵喵! 喵喵喵......