考虑将数列分成奇数项数列和偶数项数列,将
2n
个数从大到小往两个数列里放这样可以满足两个数列都是递增的
那么只要第一个数列不是满的,任何时候都可以放数进去,而第二个数列放数进去时要满足与当前项对应的第一个数列的那一项已经放了数,这样才能满足对应的奇数项小于偶数项
那么只要计算这种放法下的方案数就是序列的方案数,而这种放法和Catalan数的经典问题括号序列方案数的那个其实是一样的,将一个数放入奇数序列等价为放一个
(
,放入偶数序列等价为放一个
将柿子里所有数除以2,就是第n项Catalan数,所以长度为2n的数列的方案数就是第n项Catalan数,因为P不是质数,所以分解质因数弄一下
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 4100000;
ll ret,mod;
int pri[maxn],pr;
int mn[maxn],num[maxn];
bool v[maxn];
void get_pri(int n)
{
for(int i=2;i<=n;i++)
{
if(!v[i])
{
pri[++pr]=i;
mn[i]=i;
}
for(int j=1;j<=pr;j++)
{
int k=pri[j]*i;
if(k>n)break;
v[k]=true; mn[k]=pri[j];
if(i%pri[j]==0) break;
}
}
}
void add(int x,int c)
{
while(x!=1)
{
num[mn[x]]+=c;
x=x/mn[x];
}
}
int main()
{
int n;
scanf("%d%lld",&n,&mod);
get_pri(n<<1);
memset(num,0,sizeof num);
for(int i=n+2;i<=n<<1;i++)add(i,1);
for(int i=2;i<=n;i++)add(i,-1);
ret=1ll;
for(int i=2;i<=n<<1;i++)
{
while(num[i])
{
num[i]--;
ret=ret*(ll)i%mod;
}
}
printf("%lld\n",ret);
return 0;
}