把奇数位置的数当成一个左括号和它在序列中的对应位置,偶数位置的当成一个右括号和它的对应位置,会发现答案其实就是卡特兰数列的第 \(n\) 项。
模数不是素数,不能直接计算 \(\dfrac{\binom{2n}{n}}{n+1}\),只能手动约分。。。
#include <bits/stdc++.h> using namespace std; typedef long long i64; const int N=2000010; int n,MOD; int pri[N],pd[N],cnt[N]; int mul(int a,int b) { return i64(a)*b%MOD; } int power(int a,int e) { int r=1; for(;e;e>>=1) { if(e&1) r=mul(r,a); a=mul(a,a); } return r; } int main() { cin>>n>>MOD; if(n==1) { printf("%d\n",n%MOD); return 0; } for(int i=2;i<N;++i) pd[i]=i; int pc=0; for(int i=2;i<N;++i) { if(pd[i]==i) pri[pc++]=i; for(int j=0;i*pri[j]<N;++j) { pd[i*pri[j]]=pri[j]; if(i%pri[j]==0) break; } } for(int i=n+2;i<=2*n;++i) { int v=i; while(v>1) { int d=pd[v]; int cc=0; while(v%d==0) { v/=d; ++cc; } cnt[d]+=cc; } } for(int i=2;i<=n;++i) { int v=i; while(v>1) { int d=pd[v]; int cc=0; while(v%d==0) { v/=d; ++cc; } cnt[d]-=cc; assert(cnt[d]>=0); } } int ans=1; for(int i=2;i<N;++i) ans=mul(ans,power(i,cnt[i])); printf("%d\n",ans); return 0; }
HNOI2009 - 有趣的数列
猜你喜欢
转载自www.cnblogs.com/arg-53/p/9301958.html
今日推荐
周排行