286DIV1E. Mr. Kitayuta's Gift

Posted ichneumon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了286DIV1E. Mr. Kitayuta's Gift相关的知识,希望对你有一定的参考价值。

题目大意

给定一个由小写字母构成的字符串$s$,要求添加$n(n\le 10^9)$个小写字母,求构成回文串的数目。

简要题解

$n$辣么大,显然要矩阵快速幂嘛。

考虑从两端开始构造以s ss为子串的回文串,该回文串长度为$N=n+s$,每次添加相同的字符,则需要$(N+1)/2$次,则用dp来计算并使用矩阵乘法来优化转移会得到一个$O(|s|^6\log N)$的算法,显然是不可接受的。

考虑这个dp做法,设$f[i][j][k]$表示从两端添加了$k$次字符,原来的$s$的子串$s_{ij}$任然需要被构造出来时的方案数,我们发现会存在两种转移,一种是添加了一个字符,$s_{ij}$转移到$s_{i+1,j-1}$,这是因为$s_i=s_j$,添加一个字符可以消去$s$中两个字符,记为n25转移;另一种是$s_i\not = s_j$只消去一个字符,记为n25转移。同时要注意到,每种转移都有到自身的转移(即在回文串两端添加字符后$s_{ij}$不变,n25转移有25种添加方式转移到自身,n24转移有24种添加方式转移到自身)

我们发现其实dp可以拆成两部分来计算,一部分是计算存在$k$个n24转移的转移路径方案数,这样一来,n25的转移数为$(|s|-k+1)/2$,那么还需要添加$(N+1)/2 - k - (|s|-k+1)/2$个到自身的转移,这么一来,n24转移和n25转移的顺序就没有意义了,不妨把n24转移放到前面,n25转移放到后面,然后建图,从start到end的转移方案数就是这个图的临接矩阵的$(N+1)/2$次方。这么一来,复杂度是$O(|s|^4 \log N)$,依旧不可接受。但注意到这$k$种建图是可以合并成一个有$O(|s|)$个起点,$O(|s|)$个终点的图的,所以只需要在这一个图上做矩阵快速幂就好,复杂度为$O(|s|^3\log N)$,问题解决。还有一个优化是,该矩阵是上三角矩阵,可以利用这点来加速矩阵乘法。以上讨论基于$N$是偶数,当$N$是奇数时,注意到只有$s_{ii}$出发的n25转移是不合法的,减去即可。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 namespace my_header {
  4 #define pb push_back
  5 #define mp make_pair
  6 #define pir pair<int, int>
  7 #define vec vector<int>
  8 #define pc putchar
  9 #define clr(t) memset(t, 0, sizeof t)
 10 #define pse(t, v) memset(t, v, sizeof t)
 11 #define bl puts("")
 12 #define wn(x) wr(x), bl
 13 #define ws(x) wr(x), pc(‘ ‘)
 14     const int INF = 0x3f3f3f3f;
 15     typedef long long LL;
 16     typedef double DB;
 17     inline char gchar() {
 18         char ret = getchar();
 19         for(; (ret == \n || ret == \r || ret ==  ) && ret != EOF; ret = getchar());
 20         return ret; }
 21     template<class T> inline void fr(T &ret, char c =  , int flg = 1) {
 22         for(c = getchar(); (c < 0 || 9 < c) && c != -; c = getchar());
 23         if (c == -) { flg = -1; c = getchar(); }
 24         for(ret = 0; 0 <= c && c <= 9; c = getchar())
 25             ret = ret * 10 + c - 0;
 26         ret = ret * flg; }
 27     inline int fr() { int t; fr(t); return t; }
 28     template<class T> inline void fr(T&a, T&b) { fr(a), fr(b); }
 29     template<class T> inline void fr(T&a, T&b, T&c) { fr(a), fr(b), fr(c); }
 30     template<class T> inline char wr(T a, int b = 10, bool p = 1) {
 31         return a < 0 ? pc(-), wr(-a, b, 0) : (a == 0 ? (p ? pc(0) : p) : 
 32             (wr(a/b, b, 0), pc(0 + a % b)));
 33     }
 34     template<class T> inline void wt(T a) { wn(a); }
 35     template<class T> inline void wt(T a, T b) { ws(a), wn(b); }
 36     template<class T> inline void wt(T a, T b, T c) { ws(a), ws(b), wn(c); }
 37     template<class T> inline void wt(T a, T b, T c, T d) { ws(a), ws(b), ws(c), wn(d); }
 38     template<class T> inline T gcd(T a, T b) {
 39         return b == 0 ? a : gcd(b, a % b); }
 40     
 41 };
 42 using namespace my_header;
 43 const int maxS = 200 + 20;
 44 const int maxM = maxS * 2;
 45 const int mod = 10007;
 46 char str[maxS];
 47 int n, N, s, ans, f[maxS][maxS][maxS];
 48 inline void add(int &a, int b) {
 49     (a += b) %= mod;
 50 }
 51 inline void sub(int &a, int b) {
 52     (a -= b) %= mod;
 53     if (a < 0) a += mod;
 54 }
 55 int dp(int l, int r, int k) {
 56     int &ret = f[l][r][k];
 57     if (ret != -1)
 58         return ret;
 59     ret = 0;
 60     if (l > r)
 61         return 0;
 62     if (l == r)
 63         return ret = k == 0;
 64     if (str[l] == str[r]) {
 65         if (l == r - 1)
 66             return ret = k == 0;
 67         add(ret, dp(l + 1, r - 1, k));
 68     } else {
 69         add(ret, dp(l + 1, r, k - 1));
 70         add(ret, dp(l, r - 1, k - 1));
 71     }
 72     return ret;
 73 }
 74 struct Matrix {
 75     int d[maxM][maxM];
 76     int n;
 77     int* operator [] (int a) {
 78         return d[a];
 79     }
 80     void clear() {
 81         memset(d, 0, sizeof d);
 82     }
 83     void init() {
 84         memset(d, 0, sizeof d);
 85         for (int i = 1; i <= n; ++i)
 86             d[i][i] = 1;
 87     }
 88 };
 89 Matrix operator * (Matrix a, Matrix b) {
 90     Matrix c;
 91     c.n = a.n;
 92     c.clear();
 93     for (int i = 1; i <= a.n; ++i)
 94         for (int j = i; j <= a.n; ++j)
 95             for (int k = i; k <= j; ++k)
 96                 add(c[i][j], a[i][k] * b[k][j]);
 97     return c;
 98 }
 99 template<class T> inline T fpm(T b, int i) {
100     T r;
101     r.n = b.n;
102     r.init();
103     for (; i; i >>= 1, b = b * b)
104         if (i & 1)
105             r = r * b;
106     return r;
107 }
108 int main() {
109 #ifdef lol
110     freopen("E.in", "r", stdin);
111     freopen("E.out", "w", stdout);
112 #endif
113     cin >> (str + 1) >> n;
114     s = strlen(str + 1);
115     memset(f, -1, sizeof f);
116     for (int i = 0; i <= s; ++i)
117         f[1][s][i] = dp(1, s, i);
118     N = (s + n + 1) >> 1;
119     int n25 = (s + 1) / 2;
120     int num = s + n25;
121     Matrix x, res;
122     x.clear();
123     x.n = num + n25;
124     x[1][1] = 24;
125     for (int i = 2; i <= s; ++i) {
126         x[i][i] = 24;
127         x[i - 1][i] = 1;
128     }
129     
130     x[s][s + 1] = 1;
131     x[s + 1][s + 1] = 25;
132     x[s + 1][num + 1] = 1;
133     x[num + 1][num + 1] = 26;
134     for (int i = s + 2; i <= s + n25; ++i) {
135         x[i][i] = 25;
136         x[i - 1][i] = 1;
137         x[i][num + i - s] = 1;
138         x[num + i - s][num + i - s] = 26;
139     }
140     res = fpm(x, N);
141     for (int k = 0; k <= s - 1; ++k) {
142         int a = s - k + 1;
143         int b = s + n25 + (s - k + 1) / 2;
144         add(ans, dp(1, s, k) * res[a][b]);
145     }
146     if ((s + n) % 2 == 1) {
147         res = fpm(x, N - 1);
148         for (int k = 0; k <= s - 1; ++k)
149             if ((s - k) % 2 == 0) {
150                 int a = s - k + 1;
151                 int b = s + (s - k + 1) / 2;
152                 sub(ans, dp(1, s, k) * res[a][b]);
153             }
154     }
155     cout << ans << endl;
156     return 0;
157 }

 

以上是关于286DIV1E. Mr. Kitayuta's Gift的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #286 (Div. 1) A. Mr. Kitayuta, the Treasure Hunter DP

Mr. Kitayuta's Gift

[Codeforces 505C]Mr. Kitayuta, the Treasure Hunter

Codeforces 506E Mr. Kitayuta's Gift - 动态规划 - 矩阵

CF506E Mr. Kitayuta's Gift

Codeforces 505E Mr. Kitayuta vs. Bamboos (贪心,二分答案,堆)