Description
众所周知,完全二叉树是一种二叉树,满足除最后一层外的每层结点都是满的,且最后一层的结点连续集中在左方。而二叉堆是一种完全二叉树,分为大根堆和小根堆,大根堆满足父结点的值不小于子结点的值,小根堆满足父结点的值不大于子结点的值。
小X 最近对二叉堆和树的计数都很感兴趣,他想知道n 个互不相同的数能构成多少个不同的大小为n 的二叉堆,希望你帮帮他。
Input
第一行包含一个整数n。
Output
第一行包含一个整数,表示能构成的二叉堆个数模10^9 + 7。
Sample Input
3
Sample Output
4
Data Constraint
对于30% 的数据,n ≤ 10。
对于60% 的数据,n ≤ 1000。
对于80% 的数据,n ≤ 10^5。
对于100% 的数据,1 ≤ n ≤ 5 × 10^6。
Source / Author: 常州高级中学NOIP2014 heap
总结 : 30分暴力找规律, 没找出来。
原来是递推式很复杂。
可以设出某一限制下的方案数。
题解 :
我们f[i]表示有i个不同数字的小根堆有几种构成方案。
f
然后就处理阶乘及其逆元就行了。
#include<bits/stdc++.h>
#define open(x) freopen(x".in", "r", stdin);freopen(x".out", "w", stdout)
#define mem(a, b) memset(a, b, sizeof(a))
#define mcy(a, b) memcpy(a, b, sizeof(a))
#define pf printf
#define sf scanf
#define fo(i, a, b) for(register ll i = a; i <= b; ++i)
#define fown(i, a, b) for(register ll i = a; i >= b; --i)
#define em(p, x) for(ll p=tail[x];p;p=e[p].fr)
#define ll long long
#define wt(a, c, d, s) fo(i, c, d) pf((s), a[i]); puts("")
#define rd(a, c, d) fo(iii, c, d) in((a)[i])
#define N 5000010
#define inf 2147483647
#define mod (ll)(1e9 + 7)
using namespace std;
template<class T>
T in(T &x) {
x=0;
char ch = getchar(); ll f = 0;
while(ch < '0' || ch > '9') f |= ch == '-', ch = getchar();
while(ch >= '0' && ch <= '9') x = (x<<1) + (x<<3) + ch - '0', ch = getchar();
x = f ? -x : x;
return x;
}
ll n;
ll ans;
ll a[N], L[N], size[N];
#define ls (x << 1)
#define rs (x << 1 | 1)
ll fac[N], inv[N], f[N];
ll sqr(ll x) {return x * x % mod;}
ll power(ll x, ll p) {
if(p == 0 )return 1;
if(p & 1) return x * sqr(power(x, p / 2)) % mod;
return sqr(power(x, p / 2));
}
void init() {
fac[0] = 1;
fo(i, 1, n) fac[i] = fac[i - 1] * i % mod;
inv[n] = power(fac[n], mod - 2);
fown(i, n - 1, 0)
inv[i] = inv[i + 1] * (i + 1) % mod;
}
ll C(ll m, ll n) {
return fac[m] * inv[n] % mod * inv[m - n] % mod;
}
void DFS(ll x) {
ll S = size[x], l = L[x], r = size[x] - L[x] - 1;
if(S == 2) {
S = 2;
}
if(f[S])return ;
f[S] = 1;
if(ls > n) return ;
DFS(ls);
(f[S] *= C(S - 1, l))%=mod;
(f[S] *= f[l])%=mod;
if(rs > n) return ;
DFS(rs);
(f[S] *= f[r])%=mod;
}
void dfs(ll x) {
size[x] = 1;
if(ls > n) return ;
dfs(ls);
L[x] += size[ls];
size[x] += size[ls];
if(rs > n) return ;
dfs(rs);
size[x] += size[rs];
}
int main() {
in(n);
if(n == 1 ) {
pf("1\n");
return 0;
}
dfs(1);
init();
DFS(1);
pf("%lld\n", f[n] * 2 % mod);
return 0;
}
O(n)