SDOI2010 地精部落

SDOI2010 地精部落

题意

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

(3 leq N leq 4200)

分析

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

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

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

不难得出转移方程

(dp_i = sum binom{i - 1}{j - 1}dp_{j-1} imes 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;
}
原文地址:https://www.cnblogs.com/hznumqf/p/15007985.html