rt,我做法就是枚举左上角的拐点然后算贡献。
si,j 表示 (i,j) 往右能扩展多少点。
fi,j 表示 (i,j) 往下能扩展多少点。
gi,j 和 ki,j 分别是 C 和 F 的后缀和。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e3 + 10, P = 998244353;
int n, m, C, F, a[N][N], s[N][N], f[N][N], g[N][N], k[N][N];
signed main()
{
cin.tie(0)->ios::sync_with_stdio(false);
int _, id; cin >> _ >> id;
while (_--) {
cin >> n >> m >> C >> F;
for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) {
char c; cin >> c; a[i][j] = (c == '0');
}
int ans = 0, res = 0;
for (int i = 1; i <= n + 2; i++) for (int j = 1; j <= m + 2; j++) s[i][j] = g[i][j] = f[i][j] = k[i][j] = 0;
for (int j = m; j >= 1; j--) for (int i = n; i >= 1; i--) {
s[i][j] = (a[i][j] * s[i][j + 1] + a[i][j]) % P;
f[i][j] = (a[i][j] * f[i + 1][j] + a[i][j]) % P;
g[i][j] = (a[i][j] * g[i + 1][j] + a[i][j] * s[i][j + 1]) % P;
k[i][j] = (a[i][j] * k[i + 1][j] + a[i][j] * f[i + 1][j] * s[i][j + 1] % P) % P;
if (a[i][j]) {
(ans += s[i][j + 1] * g[i + 2][j]) %= P;
(res += s[i][j + 1] * k[i + 2][j]) %= P;
}
}
cout << ans * C % P << " " << res * F % P << "\n";
}
return 0;
}