CF1000D Yet Another Problem On a Subsequence(dp)


The sequence of integers a1,a2,…,aka1,a2,…,ak is called a good array if a1=k−1a1=k−1 and a1>0a1>0 . For example, the sequences [3,−1,44,0],[1,−99][3,−1,44,0],[1,−99] are good arrays, and the sequences [3,7,8],[2,5,4,1],[0][3,7,8],[2,5,4,1],[0] — are not.

A sequence of integers is called good if it can be divided into a positive number of good arrays. Each good array should be a subsegment of sequence and each element of the sequence should belong to exactly one array. For example, the sequences [2,−3,0,1,4][2,−3,0,1,4] , [1,2,3,−3,−9,4][1,2,3,−3,−9,4] are good, and the sequences [2,−3,0,1][2,−3,0,1] , [1,2,3,−3−9,4,1][1,2,3,−3−9,4,1] — are not.

For a given sequence of numbers, count the number of its subsequences that are good sequences, and print the number of such subsequences modulo 998244353.

Input

The first line contains the number n (1≤n≤103)n (1≤n≤103) — the length of the initial sequence. The following line contains nn integers a1,a2,…,an (−109≤ai≤109)a1,a2,…,an (−109≤ai≤109) — the sequence itself.

Output

In the single line output one integer — the number of subsequences of the original sequence that are good sequences, taken modulo 998244353.

題解:

分為 good array 和good sequence 設f(i)為i之后的答案數。\sum_{i=1}^{n} f(i) 即為所求。

對於good array         f(i)=C_{n-i}^{a[i]}

對於good sequence f(i)=\sum_{j=i+a[i]+1}^{n} C_{j-i-1}^{a[i]]}*f(j)

所以 f(i)=C_{n-i}^{a[i]}+\sum_{j=i+a[i]+1}^{n} C_{j-i-1}^{a[i]]}*f(j) 。        \sum_{i=1}^{n} f(i)即為所求。

這里我用了逆元求組合數。

#include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long ll;
using namespace std;
const int N=1100;
const int M=998244353;
int n,a[N];
ll fac[N],inv[N],f[N],ans;
ll pow_mod(ll a,int b){
	ll ans=1;a=a%M;
	while(b){
		if(b&1) ans=ans*a%M;
		a=a*a%M;b>>=1;
	} 
	return ans%M;
} 
void pre(){
	int maxn=1e3+5;fac[0]=1;
	for(int i=1;i<=maxn;i++) fac[i]=fac[i-1]*i%M;
	inv[maxn]=pow_mod(fac[maxn],M-2);
	for(int i=maxn-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%M;
} 
ll calc(int n,int m){
	if(n<m) return 0;
	return fac[n]*inv[n-m]%M*inv[m]%M; 
}
int main(){
//	freopen("D.in","r",stdin);
	pre();
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	ll ans=0;
	for(int i=n;i>=1;i--){
		if(a[i]<=0||n-i<a[i]) continue;
		f[i]=calc(n-i,a[i]);
		for(int j=i+a[i]+1;j<=n;j++){
			if(a[j]<=0 ) continue;
			f[i]=(f[i]+f[j]*calc(j-i-1,a[i])%M)%M;
		}
		ans=(ans+f[i])%M;
	}
	printf("%lld\n",ans);
	return 0;
}

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com