题意
给定 (n),求有多少个长度为 (2n) 的排列 (p) 满足
-
对于 (1leq ileq n),(p_{2i-1}<p_{2i})。
-
(p_1<p_3<cdots<p_{2n-1},p_2<p_4<cdots<p_{2n})。
答案对给定的模数 (m) 取模,不保证 (m) 为质数。
( exttt{Data Range:}1leq nleq 10^6,1leq mleq 10^9)。
题解
注意到我们可以奇偶分组,最后合并一下。
接下来考虑将因为一个小于号是 (2) 个元素,另一个是 (n) 个元素,所以考虑将排列与合法的入栈出栈过程建立映射。
如果某一个元素入栈了,那么往奇数部分填上这个元素的入栈时间,出栈的话则往偶数部分填。
由于入栈时间和出栈时间有序,而且弹掉 (n) 个元素的时间总比将 (n) 个元素入栈的时间晚,所以可以满足所有的限制。
注意到不同过程的总数就是卡塔兰数,所以答案就出来了。
但是由于这题需要组合数模合数,所以要对每个数做唯一分解,但是这样是 (O(nsqrt{n})) 的。
注意到 (1sim n) 中每个质因子对答案的贡献为 (1),(n+1) 为 (0),而 (n+2sim 2n) 为 (-1),所以我们需要求出 (1sim 2n) 的所有质因子,这个过程可以仿照埃氏筛来做。
首先可以枚举一个质数 (p),然后枚举他的倍数 (q)。接下来不断用 (q) 除掉 (p),然后顺便对答案产生贡献。容易看出每个数的每个质因子只被考虑到一次,所以复杂度是 (O(nlog n)) 的,可以通过。
代码
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef long long int li;
const ll MAXN=1e6+51;
ll n,MOD,res=1,ptot,tmp,sgn;
ll np[MAXN<<1],fct[MAXN<<1];
inline ll read()
{
register ll num=0,neg=1;
register char ch=getchar();
while(!isdigit(ch)&&ch!='-')
{
ch=getchar();
}
if(ch=='-')
{
neg=-1;
ch=getchar();
}
while(isdigit(ch))
{
num=(num<<3)+(num<<1)+(ch-'0');
ch=getchar();
}
return num*neg;
}
int main()
{
n=read(),MOD=read();
for(register int i=2;i<=2*n;i++)
{
if(!np[i])
{
for(register int j=1;i*j<=2*n;j++)
{
np[i*j]=1,tmp=i*j,sgn=i*j<=n?-1:i*j==n+1?0:1;
while(tmp%i==0)
{
fct[i]+=sgn,tmp/=i;
}
}
}
}
for(register int i=2;i<=2*n;i++)
{
while(fct[i])
{
res=(li)res*i%MOD,fct[i]--;
}
}
printf("%d
",res);
}