题目链接:点击打开链接
首先要n-=2,然后就是一个卡特兰数了。
上一题用的是 h(n) = h(n-1) * (4n-2)/(n+1);
这题用的是 h(n) = (2n)! * n! / (n+1)!;
然后对阶乘分解质因数:
分解完了直接快速幂。
#include<stdio.h>
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
#define int __int64
const int N = 100000;
int prime[N],primenum;//有primenum个素数 math.h
void PRIME(int Max_Prime){
primenum=0;
prime[primenum++]=2;
for(int i=3;i<=Max_Prime;i+=2)
for(int j=0;j<primenum;j++)
if(i%prime[j]==0)break;
else if(prime[j]>sqrt((double)i) || j==primenum-1)
{
prime[primenum++]=i;
break;
}
}
int n, m;
void mul(int &x, int y){
x *= y;
if(x >= m) x %= m;
else if(x<0) x = x%m+m;
}
int Pow(int x, int y){
int ans = 1;
while(y){
if(y&1)
mul(ans, x);
mul(x, x);
y >>= 1;
}
return ans;
}
int D[N];
void work1(int x){
for(int i = 0; prime[i]<=x; i++){
D[i] = 0;
for(int j = prime[i]; j <= x; j*=prime[i])
D[i] += x/j;
}
}
void work2(int x){
for(int i = 0; prime[i]<=x; i++)
for(int j = prime[i]; j <= x; j*=prime[i])
D[i] -= x/j;
}
void debug(){
for(int i = 0; i<primenum; i++)
if(D[i])printf("[%d,%d]\n", prime[i],D[i]);puts("");
}
int work(){
if(m==1)return 0;
if(n==1)return 1;
int res = 1;
//f[n] = 2n!/n!/(n+1)!;
work1(2*n);
work2(n);
work2(n+1);
for(int i = 0; prime[i] <= 2*n; i++)
if(D[i])
mul(res, Pow(prime[i],D[i]));
return res;
}
#undef int
int main() {
PRIME(1000000);
while(cin>>n>>m){
n-=2;
cout<< work()%m <<endl;
}
return 0;
}