传送门:
题意:求 有多少长为n的整数序列满足:
1≤Ai≤M
∣Ai−Ai+1∣≥K
分析:设dp[i][j]表示到第i位且第i位上的数字是j的合法序列数量,转移方程有:
dp[i][j]+=dp[i-1][1~j-k]+dp[i-1][j+k~m]
显然是个O(n^3)的dp。
一开始想歪了想到记忆化搜索去了,发现边数(下一个可以选的数)太多了会t
发现原方程是个区间加法的,差分一下就好了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=998244353;
int dp[1005][5005];
int ksm(int a,int b,int p)//快速幂
{
a%=p;
int ans=1;
while(b)
{
if(b&1) ans=ans*a%p;
a=a*a%p;
b>>=1;
}
return ans;
}
signed main()
{
int n,m,k;
cin>>n>>m>>k;
if(k==0)
{
cout<<ksm(m,n,mod)<<endl;
return 0;
}
for(int i=1;i<=m;i++)
{
dp[1][i]=1;
}
for(int i=1;i<=n-1;i++)
{
for(int j=1;j<=m;j++)
{
int st=j-k,ed=j+k;
if(st>=1)
{
dp[i+1][1]+=dp[i][j];
dp[i+1][1]%=mod;
dp[i+1][st+1]+=mod-dp[i][j];
dp[i+1][st+1]%=mod;
}
if(ed<=m)
{
dp[i+1][ed]+=dp[i][j];
dp[i+1][ed]%=mod;
}
}
for(int j=1;j<=m;j++)
{
dp[i+1][j]+=dp[i+1][j-1];
dp[i+1][j]%=mod;
}
}
int ans=0;
for(int i=1;i<=m;i++)
{
ans+=dp[n][i];
ans%=mod;
}
cout<<ans<<endl;
}