一个与相对大小关系相关的$DP$
设$f_{i,j,0/1}$表示放了$i$个,其中最后一个数字在$i$个中是第$j$大,且最后一个是极大值($1$)或极小值时($0$)的方案数。转移:
$$f_{i+1,j,1}=\sum\limits_{k=1}^{j-1} f_{i,k,0},f_{i+1,j,0} = \sum\limits_{k=j}^{i} f_{i,k,1}$$
发现转移可以前缀和优化,优化后复杂度为$O(n^2)$可以通过此题。
1 #include<bits/stdc++.h> 2 //This code is written by Itst 3 using namespace std; 4 5 inline int read(){ 6 int a = 0; 7 bool f = 0; 8 char c = getchar(); 9 while(c != EOF && !isdigit(c)){ 10 if(c == '-') 11 f = 1; 12 c = getchar(); 13 } 14 while(c != EOF && isdigit(c)){ 15 a = (a << 3) + (a << 1) + (c ^ '0'); 16 c = getchar(); 17 } 18 return f ? -a : a; 19 } 20 21 const int MAXN = 4210; 22 int MOD , N , dp[MAXN][MAXN][2]; 23 24 int main(){ 25 #ifndef ONLINE_JUDGE 26 freopen("2467.in" , "r" , stdin); 27 //freopen("2467.out" , "w" , stdout); 28 #endif 29 N = read(); 30 MOD = read(); 31 dp[1][1][0] = dp[1][1][1] = 1; 32 for(int i = 2 ; i <= N ; ++i){ 33 for(int j = 1 ; j <= i ; ++j){ 34 dp[i][j][0] = dp[i - 1][j][1]; 35 dp[i][j][1] = dp[i - 1][j - 1][0]; 36 } 37 for(int j = 1 ; j <= i ; ++j) 38 dp[i][j][0] = (dp[i][j][0] + dp[i][j - 1][0]) % MOD; 39 for(int j = i ; j ; --j) 40 dp[i][j][1] = (dp[i][j][1] + dp[i][j + 1][1]) % MOD; 41 } 42 cout << (dp[N][N][0] + dp[N][1][1]) % MOD; 43 return 0; 44 }