以为可以组合数分类递推求和,然而还是too naive。
设f[i]为高度小于等于i的树的方案数,那么有f[i] = (f[i - 1] ^ n) + 1。
答案为f[d] - f[d - 1]
然后敲个高精度就好啦。
话说最大数据似乎根本跑不了。
/* Footprints In The Blood Soaked Snow */
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 10005;
struct bigint {
int num[maxn], len;
bigint() {
for(int i = 0; i < maxn; i++) num[i] = 0;
len = 1;
}
void read(int x) {
for(len = 0; x; x /= 10) num[len++] = x % 10;
}
bigint operator + (const bigint &a) {
bigint c; c.len = max(len, a.len) + 1;
for(int i = 0; i < c.len; i++) {
c.num[i] += num[i] + a.num[i];
c.num[i + 1] += c.num[i] / 10;
c.num[i] %= 10;
}
for(; c.len > 1 && !c.num[c.len - 1]; c.len--);
return c;
}
bigint operator - (const bigint &a) {
bigint c; c.len = max(len, a.len);
for(int i = 0; i < c.len; i++) {
c.num[i] += num[i] - a.num[i];
if(c.num[i] < 0) {
c.num[i] += 10;
c.num[i + 1] -= 1;
}
}
for(; c.len > 1 && !c.num[c.len - 1]; c.len--);
return c;
}
bigint operator * (const bigint &a) {
bigint c; c.len = len + a.len + 1;
for(int i = 0; i < len; i++) for(int j = 0; j < a.len; j++)
c.num[i + j] += num[i] * a.num[j];
for(int i = 0; i < c.len; i++) {
c.num[i + 1] += c.num[i] / 10;
c.num[i] %= 10;
}
for(; c.len > 1 && !c.num[c.len - 1]; c.len--);
return c;
}
bigint operator ^ (int n) {
bigint ans; ans.read(1);
for(bigint t = *this; n; n >>= 1, t = t * t) if(n & 1) ans = ans * t;
for(; ans.len > 1 && !ans.num[ans.len - 1]; ans.len--);
return ans;
}
void print() {
for(int i = len - 1; i >= 0; i--) printf("%d", num[i]);
}
} f2, f1, E;
int main() {
int n, d; scanf("%d%d", &n, &d);
E.read(1); f1 = E;
for(int i = 1; i <= d; i++)
if(i & 1) f2 = (f1 ^ n) + E;
else f1 = (f2 ^ n) + E;
if(~d & 1) swap(f1, f2);
f2 = f2 - f1;
f2.print();
return 0;
}