#高精度,卡特兰数#洛谷 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;
}
posted @ 2020-06-03 20:38  lemondinosaur  阅读(130)  评论(0编辑  收藏  举报