Catalan数/组合数取模

  Aha!这题我突然灵光一现就想到Catalan数……就是按顺序安排1~2n这些数(以满足前两个条件)……分配到奇数位置上的必须比偶数位置上的多(要不就不满足第三个条件了)

  Catalan数可以用C(n,2n)/(n+1)直接求

  但是这题P不保证是质数感觉很捉急啊= =不会捉啊……然后我也没想到50分的DP,果断滚粗了啊sad QAQ

  Orz zyf & 盾爷,搬运题解:

假设现在我对于数字 i ,要把他的 j 次方加到答案中去,若k是 i 的一个质因子,那么我只要把任务交给k和i/k就可以了,因为$i^j=k^j*(\frac{i}{k})^j$,轮到算$k$或者$\frac{i}{k}$的时候只要把他的指数+上 j 即可,如果 i 是质数,直接加答案即可,因为最后的答案为整数,那么必定i的指数是正数。

【BZOJ】【1485】【HNOI2009】有趣的数列_省选互测【BZOJ】【1485】【HNOI2009】有趣的数列_排列组合_02
 1 /**************************************************************
 2     Problem: 1485
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:316 ms
 7     Memory:24708 kb
 8 ****************************************************************/
 9  
10 //BZOJ 1485
11 #include<vector>
12 #include<cstdio>
13 #include<cstdlib>
14 #include<cstring>
15 #include<iostream>
16 #include<algorithm>
17 #define rep(i,n) for(int i=0;i<n;++i)
18 #define F(i,j,n) for(int i=j;i<=n;++i)
19 #define D(i,j,n) for(int i=j;i>=n;--i)
20 using namespace std;
21  
22 int getint(){
23     int v=0,sign=1; char ch=getchar();
24     while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();}
25     while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();}
26     return v*sign;
27 }
28 typedef long long LL;
29 const int N=2000010,INF=~0u>>2;
30 /*******************tamplate********************/
31 int n,tot,MOD,p[N],v[N],b[N];
32 LL ans=1;
33 inline LL Pow_mod(LL a,LL b){
34     LL r=1;
35     for(;b;b>>=1,a=a*a%MOD) if (b&1) r=r*a%MOD;
36     return r;
37 }
38 int main(){
39 #ifndef ONLINE_JUDGE
40 //  freopen("input.txt","r",stdin);
41 //  freopen("output.txt","w",stdout);
42 #endif
43     n=getint(); MOD=getint();
44     F(i,2,n<<1){
45         if (!v[i]) p[++tot]=i;
46         F(j,1,tot){
47             if (i*p[j]>2*n) break;
48             v[i*p[j]]=p[j];
49             if (i%p[j]==0) break;
50         }
51     }
52     //ans=(n+2)*(n+3)*...*(n*2)  /(2*3*4*...*n); 
53     F(i,2,n) b[i]=-1;
54     F(i,n+2,n<<1) b[i]=1;
55     D(i,n<<1,2)
56         if (!v[i]) ans=ans*Pow_mod(i,b[i])%MOD;
57         else b[v[i]]+=b[i],b[i/v[i]]+=b[i];
58     printf("%lld\n",ans);
59     return 0;
60 }
View Code

 

1485: [HNOI2009]有趣的数列

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 777  Solved: 411
[Submit][Status][Discuss]

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)。

HINT

Source

[Submit][Status][Discuss]