本来想要复习卡特兰数没想到卡在高精度卡了好久好久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;
}