首先可以将奇数视作入栈,偶数视作出栈,那么它是卡特兰数,其实打表也能看出来,而且好像可以用dp?
不过这道题的难点不在这里,p不是素数,所以不能用求逆元来做,不过前50%的分可以用杨辉三角+达标拿到,之后的分就要用到质因数分解了。
求卡特兰数的公式:$h[n]=frac{C_{2n}^n}{n+1}$,化简之后将其分解,一开始我并没有按质因数分解,结果T了,分解质因数要更快一点。
1 void add(int x,int nu) 2 { 3 for(int i=1;prime[i]*prime[i]<=x;i++) 4 while(x%prime[i]==0) 5 { 6 cnt[prime[i]]+=nu; 7 x/=prime[i]; 8 } 9 cnt[x]+=nu; 10 } 11 for(int i=n+2;i<=2*n;i++)add(i,1); 12 for(int i=2;i<=n;i++)add(i,-1); 13 LL ans=1; 14 for(int i=2;i<=2*n;i++) 15 for(int j=1;j<=cnt[i];j++) 16 ans=ans*i%p;
1 #include<iostream> 2 #include<cstdio> 3 #define LL long long 4 //#define int LL 5 using namespace std; 6 int n,p; 7 int cnt[2000010]; 8 int prime[20010],num; 9 bool isprime[20010]; 10 #define N 20000 11 void s() 12 { 13 for(int i=2;i<=N;i++)isprime[i]=1; 14 for(int i=2;i<=N;i++) 15 { 16 if(isprime[i])prime[++num]=i; 17 for(int j=1;j<=num&&i*prime[j]<=N;j++) 18 { 19 isprime[i*prime[j]]=0; 20 if(!i%prime[j])break; 21 } 22 } 23 } 24 void add(int x,int nu) 25 { 26 for(int i=1;prime[i]*prime[i]<=x;i++) 27 while(x%prime[i]==0) 28 { 29 cnt[prime[i]]+=nu; 30 x/=prime[i]; 31 } 32 cnt[x]+=nu; 33 } 34 signed main() 35 { 36 s(); 37 cin>>n>>p; 38 for(int i=n+2;i<=2*n;i++)add(i,1); 39 for(int i=2;i<=n;i++)add(i,-1); 40 LL ans=1; 41 for(int i=2;i<=2*n;i++) 42 for(int j=1;j<=cnt[i];j++) 43 ans=ans*i%p; 44 cout<<ans<<endl; 45 }