完了,1900的DP没做出来过,数学又不行
脑子里怎么全是水呜呜
− − − − − − − − − − − − − − − − − − − − − − − − − − − − ---------------------------- −−−−−−−−−−−−−−−−−−−−−−−−−−−−
考 虑 d p , 如 何 设 计 状 态 ? 考虑dp,如何设计状态? 考虑dp,如何设计状态?
如 果 想 从 正 向 来 d p 是 比 较 困 难 的 . . . 如果想从正向来dp是比较困难的... 如果想从正向来dp是比较困难的...
如 何 去 重 , 如 何 转 移 都 是 问 题 如何去重,如何转移都是问题 如何去重,如何转移都是问题
所 以 考 虑 倒 序 d p , 定 义 d p [ i ] 是 以 i 开 头 , i 之 后 的 合 法 序 列 所以考虑倒序dp,定义dp[i]是以i开头,i之后的合法序列 所以考虑倒序dp,定义dp[i]是以i开头,i之后的合法序列
那 么 往 后 枚 举 一 个 j , j 满 足 j > a i + i 那么往后枚举一个j,j满足j>a_i+i 那么往后枚举一个j,j满足j>ai+i
现 在 i 和 j 间 有 j − i − 1 个 空 位 , 需 要 填 充 a i 个 数 字 现在i和j间有j-i-1个空位,需要填充a_i个数字 现在i和j间有j−i−1个空位,需要填充ai个数字
即 d p [ i ] + = d p [ j ] ∗ C j − i − 1 a i 即dp[i]+=dp[j]*C_{j-i-1}^{a_i} 即dp[i]+=dp[j]∗Cj−i−1ai
初 始 化 d p [ n + 1 ] = 1 , 这 是 转 移 前 驱 , 否 则 所 有 方 案 都 是 0 初始化dp[n+1]=1,这是转移前驱,否则所有方案都是0 初始化dp[n+1]=1,这是转移前驱,否则所有方案都是0
感性的理解,以n+1开头也有一种方案,就是空
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353;
int n,m,a[1009];
ll c[1009][1009],dp[1009];
void init()
{
c[0][0]=1;
for(int i=1;i<=1000;i++)
{
c[i][0]=1;
for(int j=1;j<=1000;j++)
c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
}
}
int main()
{
init();
cin >> n ;
for(int i=1;i<=n;i++) cin >> a[i];
dp[n+1]=1;
for(int i=n;i>=1;i--)
{
if( a[i]<=0||a[i]+i>n ) continue;
for(int j=i+a[i]+1;j<=n+1;j++)//从j转移过来,接在j前面
dp[i]=(dp[i]+dp[j]*c[j-i-1][a[i]]%mod )%mod;
}
ll ans=0;
for(int i=1;i<=n;i++) ans=(ans+dp[i])%mod;
cout << ans;
}