BZOJ 1485: [HNOI2009]有趣的数列 卡特兰数

xiaoxiao2021-02-28  93

Description

我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件:

(1)它是从1到2n共2n个整数的一个排列{ai}; (2)所有的奇数项满足a1<a3<…<a2n-1,所有的偶数项满足a2<a4<…<a2n; (3)任意相邻的两项a2i-1与a2i(1≤i≤n)满足奇数项小于偶数项,即:a2i-1<a2i。 现在的任务是:对于给定的n,请求出有多少个不同的长度为2n的有趣的数列。因为最后的答案可能很大,所以只要求输出答案 mod P的值。

Input

输入文件只包含用空格隔开的两个整数n和P。输入数据保证,50%的数据满足n≤1000,100%的数据满足n≤1000000且P≤1000000000。

Output

仅含一个整数,表示不同的长度为2n的有趣的数列个数mod P的值。

Sample Input 3 10 Sample Output 5 对应的5个有趣的数列分别为(1,2,3,4,5,6),(1,2,3,5,4,6),(1,3,2,4,5,6),(1,3,2,5,4,6),(1,4,2,5,3,6)。

解题方法:

http://www.cnblogs.com/beiyuoi/p/5962846.html

http://www.cnblogs.com/hapjin/p/5758083.html

///BZOJ 1485 #include <bits/stdc++.h> using namespace std; typedef long long LL; const int maxn = 2000005; LL P, ans=1; int n, cnt; bool check[maxn]; int minp[maxn], pr[maxn], c[maxn]; void predeal(int N) { minp[1]=1; for(int i=2; i<= N; i++){ if(!check[i]) pr[++cnt]=i, minp[i]=cnt; for(int j=1; j<=cnt && pr[j]*i<=N; j++){ check[pr[j]*i]=1; minp[pr[j]*i]=j; if(i%pr[j]==0) break; } } } LL powmod(LL a, LL b){ LL res=1; while(b){ if(b&1) res=res*a%P; a=a*a%P; b>>=1; } return res; } void add(int x, int v){ while(x>1){ c[minp[x]]+=v; x/=pr[minp[x]]; } } int main() { scanf("%d%lld", &n,&P); predeal(2*n); for(int i=n+2; i<=2*n; i++) add(i, 1); for(int i=1; i<=n; i++) add(i,-1); for(int i=1; i<=cnt; i++) ans=ans*powmod(pr[i], c[i])%P; printf("%lld\n", ans); return 0; }
转载请注明原文地址: https://www.6miu.com/read-51100.html

最新回复(0)