bzoj2822: [AHOI2012]树屋阶梯

来源:互联网 发布:ubuntu运行loic.exe 编辑:程序博客网 时间:2024/05/01 01:17

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2822

题意:中文题。。。

分析:我们令高度为n的时候方案数为f[n],那么我们考虑在从高度为n变成n+1时所增加的方案,因为高度为n只能用n个钢材搭建,那么变成n+1时这新加的这块放哪呢?我们把它放在"直角三角形"的直角处,我们可以看出一个高度为n的阶梯有n个台阶,那么这n个矩形每个都对应一个台阶,那么我们新放在左下角这块矩形也要对应一个台阶,那么我们就把剩下的台阶划分成了两部分,那么我们得到f[n]=f[0]*f[n-1]+f[1]*f[n-2]+...+f[n-1]*f[0]。卡特兰数,计算即可,注意要用高精度。

代码:

#include<map>#include<set>#include<cmath>#include<queue>#include<math.h>#include<cstdio>#include<vector>#include<string>#include<cstring>#include<iostream>#include<algorithm>#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;const int N=1010;const int MAX=151;const int MOD1=100000007;const int MOD2=100000009;const double EPS=0.00000001;typedef long long ll;const ll MOD=1000000007;const ll INF=10000000010;typedef unsigned long long ull;int a[N],b[N],q[N],num[N];void deal(int n) {    int i,j,k=0;    memset(q,0,sizeof(q));    for (i=2;i<=n;i++) {        if (!q[i]) { a[++k]=i;b[i]=i; }        for (j=1;j<=k;j++) {            if (a[j]*i>n) break ;            q[a[j]*i]=1;b[a[j]*i]=a[j];            if (i%a[j]==0) break ;        }    }}int ans[N];void mul(int x) {    for (int i=1;i<=ans[0];i++) ans[i]*=x;    for (int i=1;i<ans[0];i++) { ans[i+1]+=ans[i]/10;ans[i]%=10; }    while (ans[ans[0]]>9) {        ans[ans[0]+1]=ans[ans[0]]/10;        ans[ans[0]]%=10;ans[0]++;    }}int main(){    int i,j,n;    scanf("%d", &n);    deal(2*n);    for (i=1;i<=n;i++) num[i]--;    for (i=n+2;i<=2*n;i++) num[i]++;    for (i=2*n;i>1;i--)    if (!q[i]) continue ;    else { num[b[i]]+=num[i];num[i/b[i]]+=num[i];num[i]=0; }    memset(ans,0,sizeof(ans));    ans[0]=ans[1]=1;    for (i=2;i<=2*n;i++)        for (j=1;j<=num[i];j++) mul(i);    for (i=ans[0];i>0;i--) printf("%d", ans[i]);    printf("\n");    return 0;}


1 0
原创粉丝点击