#高精度,卡特兰数#洛谷 2532 [AHOI2012]树屋阶梯
分析
设\(dp[n]\)表示大小为\(n\)的树屋阶梯方案数,如何不算重也不算漏
考虑在左下角填充一个尽量大的矩形,一共有\(n\)种方法,
然后剩下的两头就可以用前面的结果表示
也就是\(dp[n]=\sum_{i=0}^{n-1}dp[i]*dp[n-i-1]\)
如果你知道这是卡特兰数的递推方法,那这题就迅速迎刃而解了
代码
#include <cstdio>
#define rr register
using namespace std;
const int N=1011,MOD=1000000000;
int ans[41],Cnt,prime[171],coun[N],n; bool v[N];
inline void doit(int n,int z){
for (rr int i=1;i<=Cnt;++i){
rr int m=n;
while (m>=prime[i])
m/=prime[i],coun[i]+=m*z;
}
}
inline void mul(int x){
rr int g=0;
for (rr int i=1;i<=ans[0];++i){
rr long long s=1ll*ans[i]*x+g;
g=s/MOD,ans[i]=s%MOD;
}
if (g) ans[++ans[0]]=g;
}
inline signed shuchu(){
printf("%d",ans[ans[0]]);
for (rr int i=ans[0]-1;i;--i)
printf("%09d",ans[i]);
return 0;
}
inline void Pro(int n){
for (rr int i=2;i<=n;++i){
if (!v[i]) prime[++Cnt]=i;
for (rr int j=1;j<=Cnt&&prime[j]*i<=n;++j){
v[i*prime[j]]=1;
if (i%prime[j]==0) break;
}
}
}
inline signed ksm(int x,int y){
rr int ans=1;
for (;y;y>>=1,x=x*x)
if (y&1) ans=ans*x;
return ans;
}
signed main(){
scanf("%d",&n),Pro(n*2),ans[ans[0]=1]=1;
doit(n*2,1),doit(n,-1),doit(n+1,-1);
for (rr int i=1;i<=Cnt;++i)
if (coun[i]) mul(ksm(prime[i],coun[i]));
shuchu();
return 0;
}