3200 [HNOI2009]有趣的数列

题面

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……当个模板记吧

原文地址:https://www.cnblogs.com/2017noipak/p/7799058.html