1. 程式人生 > 其它 >【卡特蘭數+高精度】hdu3723

【卡特蘭數+高精度】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;
}