Luogu2467 SDOI2010 地精部落 DP

传送门


一个与相对大小关系相关的$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 }

猜你喜欢

转载自www.cnblogs.com/Itst/p/10052582.html