标签:class ssi element ssis 复杂 prefix clu table etc
https://nanti.jisuanke.com/t/31434
直接搬题解:
https://www.cnblogs.com/dilthey/p/9757781.html
考虑普通的 dp[i][j]=∑a=L+1i∑b=D+1j((a==i&&b==j)?0:dp[a][b])dp[i][j]=∑a=L+1i∑b=D+1j((a==i&&b==j)?0:dp[a][b]),显然就是一整个大方块去掉一小格求和,
其中,D=max(0,i−k−1)D=max(0,i−k−1) 为下开边界,L=max(0,j−k−1)L=max(0,j−k−1) 为左开边界,
如果我们老老实实的纯暴力DP,显然就是 O(WHK2)O(WHK2) 的时间复杂度,能过有鬼……
需要使用前缀和优化,不妨假设 sum[i][j]=∑a=1i∑b=1jdp[a][b]sum[i][j]=∑a=1i∑b=1jdp[a][b],
那么,显然有状态转移方程 dp[i][j]=(sum[i−1][j]+sum[i][j−1]−sum[i−1][j−1])−(sum[D][j]+sum[i][L]−sum[D][L])dp[i][j]=(sum[i−1][j]+sum[i][j−1]−sum[i−1][j−1])−(sum[D][j]+sum[i][L]−sum[D][L]),
进而显然有状态转移方程:
sum[i][j]=(sum[i−1][j]+sum[i][j−1]−sum[i−1][j−1])+dp[i][j]=2(sum[i−1][j]+sum[i][j−1]−sum[i−1][j−1])−(sum[D][j]+sum[i][L]−sum[D][L])sum[i][j]=(sum[i−1][j]+sum[i][j−1]−sum[i−1][j−1])+dp[i][j]=2(sum[i−1][j]+sum[i][j−1]−sum[i−1][j−1])−(sum[D][j]+sum[i][L]−sum[D][L])
最后,易知答案为 dp[h][w]=sum[h][w]−(sum[h−1][j]+sum[i][w−1]−sum[h−1][w−1])dp[h][w]=sum[h][w]−(sum[h−1][j]+sum[i][w−1]−sum[h−1][w−1])。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD=998244353;
const int maxn=2000+10;
int w,h,k;
ll sum[maxn][maxn];
int main()
{
scanf("%d%d%d",&w,&h,&k);
memset(sum,0,sizeof(sum));
sum[1][1]=1;
for(int i=1;i<=h;i++)
{
for(int j=1;j<=w;j++)
{
if(i==1&&j==1) continue;
int L=max(0,i-k-1),D=max(0,j-k-1);
sum[i][j]=2*(sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1])-(sum[L][j]+sum[i][D]-sum[L][D]);
while(sum[i][j]<0) sum[i][j]+=MOD; sum[i][j]%=MOD;
}
}
ll ans=sum[h][w]-sum[h-1][w]-sum[h][w-1]+sum[h-1][w-1];
while(ans<0) ans+=MOD; ans%=MOD;
printf("%lld",ans);
}
标签:class ssi element ssis 复杂 prefix clu table etc
原文地址:https://www.cnblogs.com/hgangang/p/11562800.html