考虑进行
DP
,记 dp[i][
j]
为
(1, 1)
到
(
i
,
j
)
的方案数,此时暴力求dp的复杂度为
O
(
WHK^
2
)
,可以通过
70分
的数据。注意到转移的本质其实就是子矩阵求和,用二维前缀和优化即可做到
O
(
WH
)
。
代码:
#include <bits/stdc++.h>
using namespace std;
long long s[4001][4001],dp[4001][4001],n,m,k,ans,x_1,x_2,y_1,y_2;
int main()
{
cin>>n>>m>>k;
s[1][1] = dp[1][1] = 1;
for(int i = 1; i <= n; i++)//遍历行
for(int j = 1; j <= m; j++)//遍历列
{
if(i == 1 && j == 1) continue;
s[i][j] = (s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1]) % 998244353;//二维前缀和
if(s[i][j] < 0) s[i][j] += 998244353;//避免负数
x_1 = i - k,x_2 = i,y_1 = j - k,y_2 = j;
if(x_1 < 1) x_1 = 1;//避免越界
if(y_1 < 1) y_1 = 1;
ans = (s[x_2][y_2] - s[x_1 - 1][y_2] - s[x_2][y_1 - 1] + s[x_1 - 1][y_1 - 1]) % 998244353;
if(ans < 0) ans += 998244353;//避免负数
dp[i][j] = ans;
s[i][j] += dp[i][j];
s[i][j] %= 998244353;
}
cout<<dp[n][m] % 998244353;
return 0;
}