D. Yet Another Problem On a Subsequence(倒序dp)

完了,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,jj>ai+i

现 在 i 和 j 间 有 j − i − 1 个 空 位 , 需 要 填 充 a i 个 数 字 现在i和j间有j-i-1个空位,需要填充a_i个数字 ijji1,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]Cji1ai

初 始 化 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值