[HNOI 2009]有趣的数列

Posted NaVi_Awson

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HNOI 2009]有趣的数列相关的知识,希望对你有一定的参考价值。

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

HINT

对应的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)。

题解

我们把奇项和偶项分别按顺序拿出来,

现在解决的问题就是将$1$~$2n$分别按顺序填入每个项中,要保证奇数项中的数的个数总不小于偶数项中的数个数。

显然就是$Catalan$数了。

对于取模...因为模数$p$不一定是质数,那么就质因数分解。

 1 //It is made by Awson on 2017.10.28
 2 #include <set>
 3 #include <map>
 4 #include <cmath>
 5 #include <ctime>
 6 #include <stack>
 7 #include <queue>
 8 #include <vector>
 9 #include <string>
10 #include <cstdio>
11 #include <cstdlib>
12 #include <cstring>
13 #include <iostream>
14 #include <algorithm>
15 #define LL long long
16 #define Min(a, b) ((a) < (b) ? (a) : (b))
17 #define Max(a, b) ((a) > (b) ? (a) : (b))
18 #define Abs(x) ((x) < 0 ? (-(x)) : (x))
19 using namespace std;
20 const int N = 1000000;
21 
22 int n, pre[(N<<1)+5], prime[(N<<1)+5], tot;
23 LL p; 
24 int cnt[(N<<1)+5];
25 
26 void prepare() {
27     for (int i = 2; i <= (n<<1); i++) {
28         if (!pre[i]) prime[++tot] = i;
29         for (int j = 1; j <= tot && prime[j]*i <= (n<<1); j++) {
30             pre[prime[j]*i] = prime[j];
31             if (i%prime[j] == 0) break;
32         }
33     }
34 }
35 void work() {
36     scanf("%d%lld", &n, &p);
37     prepare();
38     for (int i = n+2; i <= (n<<1); i++) {
39         int j = i;
40         while (pre[j]) {
41             cnt[pre[j]]++; j /= pre[j];
42         }
43         cnt[j]++;
44     }
45     for (int i = 2; i <= n; i++) {
46         int j = i;
47         while (pre[j]) {
48             cnt[pre[j]]--; j /= pre[j];
49         }
50         cnt[j]--;
51     }
52     LL ans = 1;
53     for (int i = 1; i <= (n<<1); i++)
54         for (int j = 1; j <= cnt[i]; j++)
55             ans = ans*i%p;
56     printf("%lld\n", ans);
57 }
58 int main() {
59     work();
60     return 0;
61 }

 

以上是关于[HNOI 2009]有趣的数列的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1485 [HNOI2009]有趣的数列 卡特兰数

[HNOI2009]有趣的数列 题解(卡特兰数)

luogu P3200 [HNOI2009]有趣的数列

BZOJ 1485: [HNOI2009]有趣的数列 [Catlan数 质因子分解]

洛谷P3200 [HNOI2009]有趣的数列(Catalan数)

[bzoj1485] [HNOI2009]有趣的数列