dalao们都说这是一题简单的卡特兰数,画一画就出来了
emmmmm……
讲讲怎么分解质因数来算组合数
先打个表
void prim(){ ex[1]=ex[0]=1; for(int i=2;i<=2*n;i++){ if(!ex[i])pri[++cnt]=i; for(int j=1;j<=cnt&&i*pri[j]<=2*n;j++){ ex[i*pri[j]]=1; if(!(i%pri[j]))break; } } }
卡特兰数的公式是:
h(n)=C(n,2n)/(n+1)=(2n)!/((n!)*(n+1)!) = C(n, 2n) - C(n +1, 2n)
然后就可以分解质因数了
#include<iostream> #include<cstring> #include<cstdio> #include<cstdlib> using namespace std; typedef long long ll; int n,p,cnt,pri[2001000]; bool ex[2001000]; int rd(){ int x=0,fl=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')fl=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*fl; } void prim(){ ex[1]=ex[0]=1; for(int i=2;i<=2*n;i++){ if(!ex[i])pri[++cnt]=i; for(int j=1;j<=cnt&&i*pri[j]<=2*n;j++){ ex[i*pri[j]]=1; if(!(i%pri[j]))break; } } } int cal (int x,int y){ int ct=0; for(ll i=x;i<=y;i*=x) ct+=y/i; return ct; } ll ksm(int x,int y){ ll cnt=1; while(y){ if(y&1)cnt=cnt*x%p; x=x*x%p; y>>=1; } return cnt; } int main(){ n=rd();p=rd(); prim(); ll ans=1; for(int i=1;i<=cnt;i++){ int t=cal(pri[i],2*n)-cal(pri[i],n)-cal(pri[i],n+1); ans=ans*ksm(pri[i],t)%p; } printf("%lld",ans); return 0; }
emmm……当个模板记吧