【BZOJ1089】[SCOI2003]严格n元树【递推】【高精度】

以为可以组合数分类递推求和,然而还是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;
}


你可能感兴趣的:(公式,高精度)