嘟嘟嘟

 

看到回文串,就想到了manacher。而且这道题只用求长度为奇数的回文串,所以不用添加字符,在原回文串上跑一边即可。

需要注意的是,如果一个回文串的半径是r,那么这个回文串同时也包含了r - 1, r - 2,……1的回文串,因为r表示的是以 i 为回文中心的最长的回文串。于是我们开一个桶,记录回文半径长度为 i 的回文串有多少个,用前缀和的思想,差分维护区间加1。最后倒着扫一边,快速幂加速乘法。

[国家集训队]拉拉队排练_C  教程[国家集训队]拉拉队排练_编程开发_02
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<cctype>
 8 #include<vector>
 9 #include<stack>
10 #include<queue>
11 using namespace std;
12 #define enter puts("") 
13 #define space putchar(' ')
14 #define Mem(a, x) memset(a, x, sizeof(a))
15 #define rg register
16 typedef long long ll;
17 typedef double db;
18 const int INF = 0x3f3f3f3f;
19 const db eps = 1e-8;
20 const int maxn = 1e6 + 5;
21 const ll mod = 19930726;
22 inline ll read()
23 {
24   ll ans = 0;
25   char ch = getchar(), last = ' ';
26   while(!isdigit(ch)) {last = ch; ch = getchar();}
27   while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
28   if(last == '-') ans = -ans;
29   return ans;
30 }
31 inline void write(ll x)
32 {
33   if(x < 0) x = -x, putchar('-');
34   if(x >= 10) write(x / 10);
35   putchar(x % 10 + '0');
36 }
37 
38 int n;
39 ll k;
40 char s[maxn];
41 int r[maxn];
42 
43 void manacher()
44 {
45   s[0] = '@'; s[n + 1] = '$';
46   int mx = 0, id;
47   for(int i = 1; i <= n; ++i)
48     {
49       if(i < mx) r[i] = min(r[(id << 1) - i], mx - i);
50       else r[i] = 1;
51       while(s[i - r[i]] == s[i + r[i]]) r[i]++;
52       if(i + r[i] > mx) mx = i + r[i], id = i;
53     }
54 }
55 
56 ll dif[maxn];
57 ll ans = 1;
58 
59 ll quickpow(ll a, ll b)
60 {
61   a %= mod;
62   ll ret = 1;
63   while(b)
64     {
65       if(b & 1) ret = ret * a % mod;
66       a = a * a % mod; b >>= 1;
67     }
68   return ret;
69 }
70 
71 int main()
72 {
73   n = read(); k = read(); scanf("%s", s + 1);
74   manacher();
75   for(int i = 1; i <= n; ++i) dif[1]++, dif[r[i] + 1]--;
76   for(int i = 1; i <= n; ++i) dif[i] = dif[i - 1] + dif[i];
77   for(int i = (n + 1) >> 1; i; --i)
78     {
79       if(k - dif[i] > 0)
80     {
81       k -= dif[i];
82       ans *= quickpow((i << 1) - 1, dif[i]);
83       ans %= mod;
84     }
85       else
86     {
87       ans *= quickpow((i << 1) - 1, k);
88       ans %= mod;
89       k = 0; break;
90     }
91     }
92   write(k ? -1 : ans); enter;
93   return 0;
94 }
View Code