【卡特兰数+高精度】hdu3723

本来想要复习卡特兰数没想到卡在高精度卡了好久好久5555~~~


题目链接

我们很容易发现这是一道卡特兰数板子题。然后对于平走的处理就是不计入卡特兰考虑就可以了。设h[k] = C(n,2*k)*kat[k],那么答案就是sigma(k:0-->n/2) h[k]。

对于式子推一推发现h[k] = h[k-1] * (n-2*k+1) * (n-2*k+2) / ( k * (k+1) )。

之后我们用压位高精度模拟一下就可以了。

高精度的一些提醒:时刻注意函数直接传递的指针的话要小心他可能随时是变的。还有就是高精度乘的时候一定要先乘,然后考虑是否可能会有多步进位!

点击查看代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<bitset>
#include<queue>
#include<vector>
#include<cstdio>
#include<set>
#include<map>
#include<cmath>
using namespace std;

typedef long long ll;
const ll yaw = 100000;
struct gjd{
	int len;
	ll a[10000]; //5*20
	//0-->19 useful
}A,ANS;
void mul(gjd &x,ll y) {
    for(int i=0;i<=x.len;i++) x.a[i]*=y;
	for(int i=0;i<=x.len;i++) {
        if(x.a[i]>=yaw) {
            x.a[i+1] += x.a[i]/yaw;
            x.a[i]%=yaw;
        }
        if(x.a[x.len+1]) x.len++;
	}
}
void div(gjd &x,ll y) {
    ll o = 0;
	for(int i=x.len;i>=0;i--) {
        ll oo = x.a[i];
        x.a[i] = (o*yaw+oo)/y;

        o = (o*yaw+oo)%y;
	}
	while(x.len&&(!x.a[x.len])) x.len--;
}
void pint(gjd &x) {
    if(x.len<=19) {
	    printf("%lld",x.a[x.len]);
	    for(int i=x.len-1;i>=0;i--) {
	    	printf("%05lld",x.a[i]);
	    }
    } else {
        cerr<<"fuck";
        printf("%lld",x.a[19]);
        for(int i=18;i>=0;i--) {
            printf("%05lld",x.a[i]);
        }
    }
}
void ADD(gjd &x,gjd &y) {
	int le = max(x.len,y.len);
	for(int i=0;i<=le;i++) {
		x.a[i] += y.a[i];
		x.a[i+1] += x.a[i]/yaw;
		x.a[i] %= yaw;
	}
	x.len = le;
	while(x.a[x.len+1]) x.len++;
}
int main(){
    /*
    A.a[0] = 11;
    mul(A,300000); 
    ANS.len = 2;
    ANS.a[2] = 3;
    ADD(A,ANS);
    pint(A);
    */
	A.a[0]=1; ANS.a[0]=1;
	ll n; scanf("%lld",&n);
	for(ll i=1;i*2<=n;i++) {
        ll cf = (n-2*i+1ll)*(n-2*i+2ll);
		mul(A, cf);
        div(A,i*(i+1));
		ADD(ANS,A);
    }
	pint(ANS);
	return 0;
}
posted @ 2021-09-15 22:19  Newuser233  阅读(63)  评论(0编辑  收藏  举报