[ARC157C] YY Square 题解

题意

  • 给出只含 XY 的矩阵,求出所有左上到右下的路径的权值 \(v\) 的平方和,定义 \(v\) 为路径上连续的两个 Y 的数量。

分析

  • 平方比较难搞定,考虑拆贡献。令 \(f_{x,y}\) 表示到达坐标 \((x,y)\) 时的平方和,假设有 \(l\) 条到达坐标 \((x,y)\) 的路径,其权值分别为 \(v_1,v_2,\cdots,v_l\),那么就有

\[f_{x,y}=\sum_{i=1}^lv_i^2 \]

  • \(mp_{x,y+1}=mp_{x,y}=\texttt{Y}\)(对于坐标 \((x+1,y)\) 同理),则有转移

\[f_{x,y+1}=\sum_{i=1}^l(v_i+1)^2 \]

展开得到

\[f_{x,y+1}=f_{x,y}+2\sum_{i=1}^lv_i+l \]

  • \(mp_{x,y+1}\)\(mp_{x,y}\) 之间存在 X,也就是说其构不成 YY 的结构,也就没有多余的贡献,那么直接转移即可。这里的 \(\sum_{i=1}^lv_i\) 很好维护,就是一般的 \(2\) 维 DP,另外开一个 DP 数据来求即可。
  • 上面推式子为了方便写的是主动转移,下面的代码用的是被动转移。

AC 代码

#include <bits/stdc++.h>
#define int long long
#define mod 998244353
#define N 2005
using namespace std;
int n, m, cnt[N][N], f[N][N], f2[N][N], dv[2][2] = {{0, -1}, {-1, 0}};
bool mp[N][N];
char s[N];

signed main() {
	scanf("%lld%lld", &n, &m);
    for (int i = 1; i <= n; i++) {
    	scanf("%s", s + 1);
        for (int j = 1; j <= m; j++) {
        	if (s[j] == 'Y') mp[i][j] = 1;
		}
    }
    cnt[1][1] = 1;
    int x, y;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (i == 1 && j == 1) continue;
            for (int k = 0; k <= 1; k++) {
                x = i + dv[k][0], y = j + dv[k][1];
                if (x < 1 || y < 1) continue;
                cnt[i][j] = (cnt[i][j] + cnt[x][y]) % mod; //转移路径数
                if (mp[x][y] && mp[i][j]) { //都是 Y
                    f[i][j] = (f[i][j] + f[x][y] + cnt[x][y]) % mod; //权值和
                    f2[i][j] = (f2[i][j] + f2[x][y] + (f[x][y] << 1ll) + cnt[x][y]) % mod; //权值平方和
                } else { //存在 X
                    f[i][j] = (f[i][j] + f[x][y]) % mod;
                    f2[i][j] = (f2[i][j] + f2[x][y]) % mod;
                }
            }
        }
    }
    printf("%lld", f2[n][m]);
    return 0;
}
posted @ 2024-02-27 19:48  wswwhcs  阅读(6)  评论(0编辑  收藏  举报