Loading

SDOI2010 地精部落

SDOI2010 地精部落

题意

求所有数都是波峰或者波谷的\(1-N\)序列个数

\(3 \leq N \leq 4200\)

分析

借鉴以前学习的插入型DP的思想。

容易发现把第一个数设置为波谷和波峰得到的答案是一样的,所以不妨令第一个数为波峰

\(dp[i]\)表示\(1-i\)的序列个数,现在要插入\(i + 1\),那么\(i + 1\)一定会是波峰,插入的位置就必须在奇数位置的右边

不难得出转移方程

\(dp_i = \sum \tbinom{i - 1}{j - 1}dp_{j-1}\times dp_{i-j}\)

代码

实现上注意这题模数给定,不要用快速幂求逆元的方法,直接递推即可

#include<bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;

typedef long long ll;

ll rd(){
	ll x;
	scanf("%lld",&x);
	return x;
}

const int maxn = 1e4 + 5;

int C[2][maxn];
int MOD;

int main(){
	int n = rd();
	MOD = rd();
	vector<int> dp(n + 1);
	dp[0] = 1;
	C[0][0] = C[1][0] = 1;
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= i;j++){
			if(j & 1) dp[i] += (ll)dp[j - 1] * dp[i - j] % MOD * C[1 ^ (i & 1)][j - 1] % MOD,dp[i] %= MOD; 
			C[i & 1][j] = (C[(i & 1) ^ 1][j - 1] + C[(i & 1) ^ 1][j]) % MOD;
		}
	}
	cout << dp[n] * 2 % MOD;
}
posted @ 2021-07-13 19:03  MQFLLY  阅读(30)  评论(0编辑  收藏  举报