solution.md 2.4 KB
Newer Older
每日一练社区's avatar
每日一练社区 已提交
1
# 堆的计数
F
fix bug  
feilong 已提交
2

3
**题目描述**
F
fix bug  
feilong 已提交
4

每日一练社区's avatar
每日一练社区 已提交
5
我们知道包含N个元素的堆可以看成是一棵包含N个节点的完全二叉树。  
每日一练社区's avatar
每日一练社区 已提交
6

每日一练社区's avatar
每日一练社区 已提交
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
每个节点有一个权值。对于小根堆来说,父节点的权值一定小于其子节点的权值。  
 
假设N个节点的权值分别是1~N,你能求出一共有多少种不同的小根堆吗?  
 
例如对于N=4有如下3种:
```
    1
   / \
  2   3
 /
4
 
    1
   / \
  3   2
 /
4
 
    1
   / \
  2   4
 /
3
 
```
每日一练社区's avatar
每日一练社区 已提交
32

每日一练社区's avatar
每日一练社区 已提交
33 34 35
由于数量可能超过整型范围,你只需要输出结果除以1000000009的余数。  
 
 
36
**输入格式**
F
fix bug  
feilong 已提交
37

每日一练社区's avatar
每日一练社区 已提交
38
一个整数N。  
每日一练社区's avatar
每日一练社区 已提交
39

每日一练社区's avatar
每日一练社区 已提交
40
对于40%的数据,1 <= N <= 1000  
每日一练社区's avatar
每日一练社区 已提交
41

每日一练社区's avatar
每日一练社区 已提交
42
对于70%的数据,1 <= N <= 10000  
每日一练社区's avatar
每日一练社区 已提交
43

每日一练社区's avatar
每日一练社区 已提交
44 45
对于100%的数据,1 <= N <= 100000
 
46
**输出格式**
F
fix bug  
feilong 已提交
47

每日一练社区's avatar
每日一练社区 已提交
48 49
一个整数表示答案。  
 
50
**输入样例**
F
fix bug  
feilong 已提交
51

每日一练社区's avatar
每日一练社区 已提交
52 53 54 55
```
4
```  
 
56
**输出样例**
F
fix bug  
feilong 已提交
57

每日一练社区's avatar
每日一练社区 已提交
58 59 60
```
3
``` 
每日一练社区's avatar
每日一练社区 已提交
61

62
**资源约定:**
F
fix bug  
feilong 已提交
63

每日一练社区's avatar
每日一练社区 已提交
64
峰值内存消耗(含虚拟机) < 256M  
每日一练社区's avatar
每日一练社区 已提交
65

每日一练社区's avatar
每日一练社区 已提交
66 67
CPU消耗  < 1000ms

每日一练社区's avatar
每日一练社区 已提交
68
下面的代码实现了这一功能,请你补全空白处缺失的代码:
F
fix bug  
feilong 已提交
69

每日一练社区's avatar
每日一练社区 已提交
70 71 72
```cpp
#include <bits/stdc++.h>
using namespace std;
每日一练社区's avatar
每日一练社区 已提交
73

每日一练社区's avatar
每日一练社区 已提交
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
typedef long long ll;
const int maxn = 100000;
ll s[maxn + 10], dp[maxn + 10], inv[maxn + 10], f[maxn + 10];
ll n;
ll mod = 1000000009;
ll qPow(ll a, ll b)
{
    ll ans = 1;
    while (b != 0)
    {
        if (b & 1)
        {
            ans = ans * a % mod;
        }
        a = a * a % mod;
        b >>= 1;
    }
    return ans % mod;
}
ll C(ll n, ll m)
{
    return (f[n] * inv[f[m]]) % mod * inv[f[n - m]] % mod;
}
F
fix bug  
feilong 已提交
97

每日一练社区's avatar
每日一练社区 已提交
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
int main()
{
    cin >> n;
    f[0] = 1;
    for (int i = 1; i <= maxn; i++)
    {
        f[i] = (f[i - 1] * i) % mod;
        inv[i] = qPow(i, mod - 2);
    }
    for (int i = n; i >= 1; i--)
    {
        s[i] = (s[i * 2 + 1] <= n ? s[i * 2 + 1] : 0) + (s[i * 2] <= n ? s[i * 2] : 0) + 1;
    }
    for (int i = 1; i <= n; i++)
    {
        dp[i] = 1;
    }
    for (int i = n; i >= 1; i--)
    {
        if (i * 2 + 1 <= n)
        {
每日一练社区's avatar
每日一练社区 已提交
119
            __________________
每日一练社区's avatar
每日一练社区 已提交
120 121 122 123 124 125
        }
    }
    cout << dp[1] << endl;
    return 0;
}
```
每日一练社区's avatar
每日一练社区 已提交
126 127 128 129 130 131 132 133

## aop

### before

```cpp

```
每日一练社区's avatar
每日一练社区 已提交
134

每日一练社区's avatar
每日一练社区 已提交
135 136 137 138 139 140 141 142 143 144 145
### after

```cpp

```

## 答案

```cpp
dp[i] = (C(s[i] - 1, s[i * 2 + 1]) * dp[i * 2 + 1]) % mod * dp[i * 2] % mod;
```
每日一练社区's avatar
每日一练社区 已提交
146 147
## 选项

F
fix bug  
feilong 已提交
148

每日一练社区's avatar
每日一练社区 已提交
149
### A
F
fix bug  
feilong 已提交
150

每日一练社区's avatar
每日一练社区 已提交
151
```cpp
每日一练社区's avatar
每日一练社区 已提交
152
dp[i] = (C(s[i], s[i * 2 + 1]) * dp[i * 2 + 1]) % mod * dp[i * 2 + 1] % mod;
每日一练社区's avatar
每日一练社区 已提交
153 154 155
```

### B
F
fix bug  
feilong 已提交
156

每日一练社区's avatar
每日一练社区 已提交
157
```cpp
每日一练社区's avatar
每日一练社区 已提交
158
dp[i] = (C(s[i] - 1, s[i * 2]) * dp[i * 2]) % mod * dp[i * 2] % mod;
每日一练社区's avatar
每日一练社区 已提交
159 160 161
```

### C
F
fix bug  
feilong 已提交
162

每日一练社区's avatar
每日一练社区 已提交
163
```cpp
每日一练社区's avatar
每日一练社区 已提交
164
dp[i] = (C(s[i] + 1, s[i * 2 + 1]) * dp[i * 2 + 1]) % mod * dp[i * 2] % mod;
每日一练社区's avatar
每日一练社区 已提交
165
```