乍一看很简单,求卡特兰数的模,但是(1 <= n <= 100000),数据有点可怕。
(1)用卡特兰数的递推公式 h(n)=h(n-1)*(4*n-2)/(n+1) ,但是除以(n+1)在模m的情况下无法计算(用逆元似乎也不能算出来),因此采用方法2.
(2)用卡特兰数的组合数公式 h(n)=C(2n,n)/(n+1) ,同样的问题,除以(n+1)不好算,所以只能直接对C(2n,n)的所有项分解质因数
当然不能直接裸暴力枚举所有项和他们的质因数,那样的话时间复杂度是O(n^2)肯定会超时,因此仅枚举所有质数,用count(n,prime[i])函数计算1-n共有多少个prime[i],这样做,算法复杂度是O(klogn) + O(n)(预处理质数表),k是所有质因数的个数。
#include <cstdio>
int n,m,t;
long long ans;
int prime[100000],pp,cnt;
void init()
{
prime[0]=2;
pp=1;
for (int i=3;i<=200000;i+=2)
{
bool f=1;
for (int j=0;j<pp;j++)
if (i%prime[j]==0) {f=0; break;}
if (f) prime[pp++]=i;
}
}
int count(int a,int b)
{
int res=0;
while (a>=b)
{
res+=a/b;
a/=b;
}
return res;
}
long long pow_mod(long long x,int y)
{
long long res=1;
while (y)
{
if (y&1) res=(res*x)%m;
x=(x*x)%m;
y>>=1;
}
return res;
}
int main()
{
init();
while (scanf("%d%d",&n,&m)==2)
{
ans=1;
for (int i=0;i<pp;i++)
{
cnt=count(n+n,prime[i])-count(n,prime[i])-count(n+1,prime[i]);
ans=(ans*pow_mod(prime[i],cnt))%m;
}
printf("%lld\n",ans);
}
return 0;
}