BZOJ 1485: [HNOI2009]有趣的数列

对任意前缀,前 \(n\) 个数被选的不小于没被选的,否则,即使奇数项贴着下界继续放,偶数项也会不满足第 \(2\) 或 第 \(3\) 个条件。
所以就变成了卡特兰数的定义
\(C_n = \binom{2n}{n} - \binom{2n}{n+1}=\dfrac{2n!}{n!(n+1)!}\)
组合数对合数取模,枚举每一个质因子的贡献即可

#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define pii pair<int, int>
#define lp p << 1
#define rp p << 1 | 1
#define mid ((l + r) >> 1)
#define ll long long
#define db double
#define rep(i,a,b) for(int i=a;i<b;i++)
#define per(i,a,b) for(int i=b-1;i>=a;i--)
#define Edg int cnt=1,head[N],to[N*2],ne[N*2];void addd(int u,int v){to[++cnt]=v;ne[cnt]=head[u];head[u]=cnt;}void add(int u,int v){addd(u,v);addd(v,u);}
#define Edgc int cnt=1,head[N],to[N*2],ne[N*2],c[N*2];void addd(int u,int v,int w){to[++cnt]=v;ne[cnt]=head[u];c[cnt]=w;head[u]=cnt;}void add(int u,int v,int w){addd(u,v,w);addd(v,u,w);}
#define es(u,i,v) for(int i=head[u],v=to[i];i;i=ne[i],v=to[i])

const int N = 2e6 + 7;
int MOD, prime[N], prin;
int qp(int a, int b) {
	int ans = 1;
	for (; b; a = 1LL * a * a % MOD, b >>= 1) 
		if (b & 1) ans = 1LL * a * ans % MOD;
	return ans % MOD;
}

int solve(int n, int p) {
	int base = p;
	int ans = 0;
	while (base <= n) {
		ans += n / base;
		if (1LL * base * p > n) break;
		base *= p;
	}
	return ans;
}

int main() {
	int n;
	scanf("%d%d", &n, &MOD);
	static bool vis[N];
	rep (i, 2, 2 * n + 2) {
		if (!vis[i]) prime[++prin] = i;
		rep (j, 1, prin + 1) {
			if (1LL * i * prime[j] >  2 * n + 1) break;
			vis[i * prime[j]] = 1;
			if (i % prime[j] == 0) break;
		}
	}
	int ans = 1;
	rep (i, 1, prin + 1) {
		int cnt = solve(2 * n, prime[i]) - solve(n, prime[i]) - solve(n + 1, prime[i]);
		ans = 1LL * ans * qp(prime[i], cnt) % MOD;
	}
	printf("%d\n", ans);
}
posted @ 2020-02-21 22:18  Mrzdtz220  阅读(84)  评论(0)    收藏  举报