给定一个 n 行 m 列的只包含小写字母的矩阵 A,请求出从 (1,1) 到 (n,m) 只向下或向右走,且路径上的所有字符按照顺序排列可以构成一个回文串的路径条数。
由于答案可能很大,请输出答案在模 993244853 意义下的结果。
输入样例1:
3 4
noip
ffff
pion
输出样例1:
2
数据范围:
对于 20% 的数据,1≤n,m≤10。
对于 35% 的数据,1≤n,m≤20。
对于 50% 的数据,1≤n,m≤80。
另有 15% 的数据,1≤n≤80。
另有 15% 的数据,保证对任意 1<i,j<m 有 A[i][j]=A[i−1][j+1]。
对于 100% 的数据,1≤n,m≤500,输入的矩阵仅包含小写英文字母。
暴力枚举左上角和右下角 DP,复杂度O(n^4) .
观察到只有x1 + x2 + y1 + y2 = n + m + 2的状态才有用,因此我们枚举x1, y1, x2,即可得知y2,复杂度降为 O(n^3) .代码如下:
#include <bits/stdc++.h>
using namespace std;
#define ll int
const int N = 85, NN = 505;
const int dx[4] = {
-1, 0, 1, 0}, dy[4] = {
0, -1, 0, 1}; // 上 左 下 右
const ll mod = 993244853;
int n, m;
char mp[N][NN];
ll f[N][NN][N], g[NN][NN];
bool st[N][NN][N];
void AddMod(ll &p, ll k) {
p = (p + k) % mod; }
ll solve(int x1, int y1, int x2, int y2) {
// printf("[%d, %d, %d, %d]\n", x1, y1, x2, y2);
if (abs(x1 - x2) + abs(y1 - y2) <= 1) return f[x1][y1][x2] = 1;
if (x1 > x2 || y1 > y2) return 0;
if (st[x1][y1][x2]) return f[x1][y1][x2];
for (