洛谷P3200:https://www.luogu.org/problemnew/show/P3200
思路
这题明显是卡特兰数的题型咯
一看精度有点大
如果递推卡特兰数公式要到O(n2)
可以证明得出分子可以把分母约到只剩1
那我们就可以用分解质因数的方法 把分子分母全都质因数分解
再把分母约掉 就可以直接把分子剩下的质因数乘起来即可
代码
#include<iostream> #include<cstdio> using namespace std; #define ll long long #define maxn 200000020 ll n,P,ans=1; int p[maxn/10],v[maxn/10],z[maxn]; void primes(ll n) { ll k=0; for(ll i=2;i<=n;i++) { if(!v[i]) { v[i]=i; p[++k]=i; } for(ll j=1;j<=k;j++) { if(p[j]>v[i]||p[j]*i>n) break; v[i*p[j]]=p[j]; } } } ll quickpow(ll a,ll b) { ll ret=1; while(b) { if(b%2==1) ret=ret*a%P; a=a*a%P; b/=2; } return ret; } int main() { scanf("%lld%lld",&n,&P); primes(2*n);//建立素数表和每个数的最小因子 for(ll i=2*n;i>=n+2;i--)//把分子质因数分解 { ll k=i; while(k>1) { z[v[k]]++;//这个质数的指数加1 k/=v[k]; } } for(ll i=2;i<=n;i++)//把分母质因数分解 { ll k=i; while(k>1) { z[v[k]]--;//约掉分子分母相同的质数 k/=v[k]; } } for(ll i=2;i<=2*n;i++) ans=(ans*quickpow(i,z[i]))%P;//把剩下的所有数相乘 printf("%lld",ans); }