题目大意:定义严格 $n$ 元树为所有非叶节点都恰好有 $n$ 个儿子,求深度为 $d$ 的严格 $n$ 元树的个数。$0 < n \leq 32, 0 \leq d \leq 16$
设 $f[i]$ 表示深度小于等于 $i$ 的严格 $n$ 元树的个数,有
另外这题的数据范围根本不可做,因为数字长度 $l$ 可以达到 $n^d$,实际上测试数据的范围是 $n^d \leq 1024$。
#include <cstdio>
#include <cstring>
const int BAS = 10000, WID = 4;
struct Big {
int x[100000];
Big() { memset(x, 0, sizeof x); }
Big operator + (const int &a) {
Big b; b.x[0] = x[0], b.x[1] = a;
for (int i = 1; i <= b.x[0]; ++i)
b.x[i] += x[i], b.x[i+1] = b.x[i] / BAS, b.x[i] %= BAS;
if (b.x[b.x[0]+1]) ++b.x[0];
return b;
}
void operator -= (const Big &a) {
for (int i = 1; i <= x[0]; ++i) {
if (x[i] < a.x[i]) --x[i+1], x[i] += BAS;
x[i] -= a.x[i];
}
while (!x[x[0]] && x[0] > 1) --x[0];
}
void operator *= (const Big &a) {
Big b;
for (int i = 1; i <= x[0]; ++i)
for (int j = 1; j <= a.x[0]; ++j)
b.x[i+j-1] += x[i] * a.x[j], b.x[i+j] += b.x[i+j-1] / BAS, b.x[i+j-1] %= BAS;
x[0] += a.x[0], x[1] = 0;
for (int i = 1; i <= x[0]; ++i)
x[i] += b.x[i], x[i+1] = x[i] / BAS, x[i] %= BAS;
while (!x[x[0]] && x[0] > 1) --x[0];
}
void print() {
printf("%d", x[x[0]]);
for (int i = x[0] - 1; i; --i) printf("%0*d", WID, x[i]);
puts("");
}
} f[20];
Big fast_pow(Big a, int b) {
Big res;
res.x[++res.x[0]] = 1;
for (; b; b >>= 1, a *= a)
if (b & 1) res *= a;
return res;
}
int main() {
int n, d; scanf("%d%d", &n, &d); ++d;
f[0].x[0] = 1;
for (int i = 1; i <= d; ++i)
f[i] = fast_pow(f[i-1], n) + 1;
f[d] -= f[d-1], f[d].print();
return 0;
}
时间复杂度 $O(l^2 d \log n)$