Subtrees
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 105 Accepted Submission(s): 59
Problem Description
There is a complete binary tree with N nodes.The subtree of the node i has Ai nodes.How many distinct numbers are there of Ai?
Input
There are multiple test cases, no more than 1000 cases.
For each case contains a single integer N on a line. (1≤N≤1018)
For each case contains a single integer N on a line. (1≤N≤1018)
Output
The output of each case will be a single integer on a line:the number of subtrees that contain different nodes.
Sample Input
5 6 7 8
Sample Output
3 4 3 5
Source
题解:
一颗完全二叉树,左右子树都会为完全二叉树,其中必然有一个最后一层是满的。对于最后一层是满的完全二叉树,每一层的节点的子树形态都是相同的,只统计logN种,然后递归处理另一颗子树。最后对记录下的所有子树根据节点数判重.
判重的时候我们可以用一个map就轻松实现了. 整个算法的复杂度log(N).
或者明确一点的说, N个节点构成的完全二叉树, 除去根节点, 我们该如何将剩下的N - 1个节点分成两个完全二叉数, 这就是解这道题的关键.
#include <cstdio>
#include <cstring>
#include <map>
using namespace std;
typedef long long LL;
map<LL, bool> mp;
LL fun(LL x) {
if (x <= 0) return 0;
LL t = 1;
for (LL i = 1; (t - 1) * 2 < x; ++i)
t *= 2;
if ((t - 1) * 2 == x || (t - 1) + (t - 1) / 2 <= x)
return t - 1;
else
return t / 2 - 1;
}
void solve(LL n) {
mp[n] = true;
LL x = fun(n - 1);
if (x > 0 && mp[x] == false)
solve(x);
x = n - x - 1;
if (x > 0 && mp[x] == false)
solve(x);
}
int main() {
LL n;
while (~scanf("%lld", &n)) {
mp.clear();
solve(n);
printf("%ld\n", mp.size());
}
return 0;
}