http://acm.hdu.edu.cn/showproblem.php?pid=5136
题意
最长链为k的度<=3的无标号树个数
题解
- 若k为奇数,我们取最长链的中心,连出>=2个深度=[k/2]的二叉树。即
(CA([k/2])2+CA([k/2])1))×S([k/2]−1)+(CA([k/2])3+2CA([k/2])2+CA([k/2])1) - 若k为偶数数,我们在最长链的中间假想一个虚拟点,连出2个深度=k/2的二叉树。即
(CA(k/2)2+CA(k/2)1)
其中A(n)为深度为n的二叉树个数,S(n)为A(n)部分和。同理对深度为n的二叉树,根连出>=1个深度为n-1的二叉树。
A(n)=A(n−1)×S(n−2)+(CA(n−1)2+CA(n−1)1)
code
//by wangtianyu
#include <cstdio>
typedef long long LL;
const int mod = 1000000007;
const int N = 101000;
struct modn {
int n;
modn() { }
modn(LL x) { n = (x < 0 ? (((x%mod)+mod)%mod) : x%mod); }
void print() const { printf("%d\n", n); }
};
modn operator +(const modn& A, const modn& B) { return A.n+B.n; }
modn operator -(const modn& A, const modn& B) { return A.n-B.n; }
modn operator *(const modn& A, const modn& B) { return (LL)A.n*B.n; }
modn power(const modn& a, LL n) {
modn s = 1, t = a;
for (; n; n >>= 1) {
if (n&1) s = s * t;
t = t * t;
}
return s;
}
const modn inv2 = power(2, mod-2);
const modn inv6 = power(6, mod-2);
modn g[N], s[N];
modn C3(modn x) {
if (x.n < 3) return 0;
return x * (x - 1) * (x - 2) * inv6;
}
modn C2(modn x) {
if (x.n < 2) return 0;
return x * (x - 1) * inv2;
}
int main() {
int n;
while(scanf("%d", &n) != EOF && n) {
g[0] = g[1] = 1;
s[0] = 1;
s[1] = 2;
for (int i = 2; i <= n; i ++)
g[i] = C2(g[i - 1]) + g[i - 1] + g[i - 1] * s[i - 2], s[i] = s[i - 1] + g[i];
modn ans;
if (n & 1) {
n = n / 2;
ans = C3(g[n]) + g[n] * g[n] + (C2(g[n]) + g[n]) * s[n - 1];
} else {
n = n / 2;
ans = C2(g[n]) + g[n];
}
ans.print();
}
return 0;
}