http://codeforces.com/problemset/problem/1000/D
Reference from: https: //www.cnblogs.com/hua-dong/p/9238795.html
The meaning of problems: a given sequence, asked how many sequences (not necessarily consecutive), meet can be divided into several groups, the interval length is equal to the first set of -1;
Ideas: the key lies in the beginning of the interval, which we consider forward from the back, dp [i] represents the beginning with i, to meet the meaning of the title number, sum [i] and i represent all possible situations in the future.
For i, optional interval [i, j], j is the range of i + a [i] ~ n, again using the selected thinking, this period may range where there is C (a [i] -1 , j - i -1), then multiplied by (1 + sum [j +1]),
This is thought to use multiplication, and this represents a case where only a selected segment of the foregoing, is obtained through continuous accumulation dp [i], and then get accumulated sum [i].
#include<bits/stdc++.h> #define ll long long using namespace std; const int Mod=998244353; const int maxn=1010; int a[maxn],dp[maxn],sum[maxn]; int c[maxn][maxn],ans; int main() { int N,i,j; scanf("%d",&N); for(i=0;i<=N;i++) c[i][0]=1,c[i][1]=i,c[i][i]=1; for(i=1;i<=N;i++) for(j=1;j<=N;j++) c[i][j]=(c[i-1][j]+c[i-1][j-1])%Mod; for(i=1;i<=N;i++) scanf("%d",&a[i]); for(i=N;i>=1;i--){ if(a[i]>0&&i+a[i]<=N){ for(j=i+a[i];j<=N;j++){ (dp[i]+=(ll)c[j-i-1][a[i]-1]*(1SUM + [J + 1 ]) Mod%) Mod% =; // here refers to a case where only a segment of the printf ( " % D% D \ n- " , C [Ji- 1 ] [A [I] - 1 ], ( . 1 + SUM [J + . 1 ])); } } SUM [I] = (SUM [I + . 1 ] + DP [I])% Mod; // the printf ( "% D \ n-", SUM [I] ); } the printf ( " % D \ n- " , SUM [ . 4 ]); return 0 ; } // #include <the iostream> // #include <cstdio> // #include <cstdlib> // #include <cstring> // #include <cmath> // #define qwq(i,j,k) for(int i=j; i<k; ++i) // #define qeq(i,j,k) for(int i=j; i<=k; ++i) // #define mem(a,b) memset(a, b, sizeof(a)) // using namespace std; // typedef long long ll; // const int mx = 1e5+5; // const int maxn = 3e3+5; // const int inf= 0x3f3f3f3f; // // const ll mod = 1e9+7; // const ll INF = 1e18+100; // int n, m; // int cas, tol, T; // ll C[maxn][maxn]; // ll fac[mx]; //i! // ll inv[mx]; //i!在取模mod的情况下的逆元 // // ll fpow(ll a, ll b) { // // ll ans = 1; // // while(b) { // // if(b & 1) // // ans = ans * a % mod; // // a = a * a % mod; // // b >>= 1; // // } // // return ans; // // } // const ll mod=998244353; // void handle() { // // fac[0] = 1; // // for(int i=1; i<=mx; ++i) { // // fac[i] = fac[i-1]*i%mod; //阶乘的表 // // } // // inv[mx] = fpow(fac[mx], mod-2); // // for(int i=mx-1; i>=1; --i) { // // inv[i] = inv[i+1] * (i+1) % mod; // // } // C[0][0] = 1; // C[1][0] = C[1][1] = 1; // for(int i=2; i<maxn; ++i) { // for(int j=0; j<=i; ++j) { // C[i][j] = j==0 ? 1 : (C[i-1][j]%mod+C[i-1][j-1]%mod)%mod; // } // } // } // ll a[maxn]; // ll b[maxn]; // ll ans; // int main() { // //打表O(N^2) n 1e3左右 // handle(); // // for(int i=1; i<=10; ++i) { // // for(int j=0; j<=i; ++j) { // // printf("C[%d][%d] = %lld\n", i, j, C[i][j]); // // } // // } // ans=0; // scanf("%d",&n); // for(int i=1; i<=n; i++){ // cin>>a[i]; // } // for(int i=1; i<=n; i++){ // if(a[i]>0 && a[i]+i<=n){ // b[i] = C[n-i][ a[i] ]; // } // } // for(int i=n-1; i>=1; i--){ // if(b[i]!=0){ // ll sum=0; // for(int j=n-1; j>=i+a[i]+1; j--){ // // if(a[j]>0 && a[j]+j<=n){ // b[i] += b[j]; // // } // // if(i==4) printf("b[4]=%lld\n", b[i]); // } // // b[i] = (b[i]%mod + b[ i+a[i]+1 ]%mod)%mod; // ans = (ans+b[i])%mod; // } // } // printf("%d\n", b[2]); // cout<<ans<<endl; // return 0; // }