UVA1478 Delta Wave 题解
思路
若不能往右走,则本题就是卡特兰数。
现在加上可以往右走的条件,可以在一开始都往右走的前提下任选 \(k\) 个右上,\(k\) 个右下,并且不能碰到 \(y = -1\)。因此方案数为:
\[\sum\limits_{k=1}^{\left\lfloor\frac{n}{2}\right\rfloor} C_{n}^{2k} f_k + 1
\]
其中 \(f_k\) 为第 \(k\) 项卡特兰数,\(+1\) 是因为还要算全部往右走的方案。
直接高精计算显然会 T,考虑算出连续两项的比值 \(= \dfrac{(n-2k+1)(n-2k+2)}{k(k+1)}\),就可以高精乘低精 + 高精除低精 + 高精加高精过了。
代码
code
/*
p_b_p_b txdy
AThousandSuns txdy
Wu_Ren txdy
Appleblue17 txdy
*/
#include <bits/stdc++.h>
#define pb push_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;
const int maxn = 1010;
const ll B = 10000000000LL;
ll ans[maxn], a[maxn], ta[maxn], n;
void add(ll *a, ll &lena, ll *b, ll &lenb) {
memset(ta, 0, sizeof(ta));
ll nl = min(max(lena, lenb), 10LL);
for (int i = 0; i < nl; ++i) {
ta[i] = a[i] + b[i];
}
for (int i = 0; i < nl; ++i) {
if (ta[i] >= B) {
ta[i + 1] += ta[i] / B;
ta[i] %= B;
}
}
while (ta[nl]) {
++nl;
}
memcpy(a, ta, sizeof(ta));
lena = nl;
}
void mul(ll *a, ll &lena, ll b) {
memset(ta, 0, sizeof(ta));
ll nl = lena;
for (int i = 0; i < nl; ++i) {
ta[i] = a[i] * b;
}
for (int i = 0; i < nl; ++i) {
if (ta[i] >= B) {
ta[i + 1] += ta[i] / B;
ta[i] %= B;
}
}
while (ta[nl]) {
ta[nl + 1] += ta[nl] / B;
ta[nl] %= B;
++nl;
}
memcpy(a, ta, sizeof(ta));
lena = nl;
}
void div(ll *a, ll &lena, ll b) {
memset(ta, 0, sizeof(ta));
ll nl = lena, rem = 0;
for (int i = nl - 1; ~i; --i) {
ta[i] = (rem * B + a[i]) / b;
rem = (rem * B + a[i]) % b;
}
while (!ta[nl - 1]) {
--nl;
}
memcpy(a, ta, sizeof(ta));
lena = nl;
}
void solve() {
memset(ans, 0, sizeof(ans));
memset(a, 0, sizeof(a));
ll lena = 1, lenb = 1;
a[0] = ans[0] = 1;
for (int i = 1; i <= n / 2; ++i) {
mul(a, lenb, (n - 2 * i + 1) * (n - 2 * i + 2));
div(a, lenb, i * (i + 1));
add(ans, lena, a, lenb);
}
bool flag = 1;
for (int i = min(lena - 1, 9LL); ~i; --i) {
if (ans[i]) {
if (flag) {
printf("%lld", ans[i]);
flag = 0;
} else {
printf("%010lld", ans[i]);
}
}
}
putchar('\n');
}
int main() {
// int T = 1;
// scanf("%d", &T);
while (scanf("%lld", &n) == 1) {
solve();
}
return 0;
}