Consider a binary tree whose leaves are assigned integer weights. Such a tree is called balanced
if, for every non-leaf node, the sum of the weights in its left subtree is equal to that in the right
subtree. For instance, the tree in the following figure is balanced.
Figure I.1. A balanced tree
A balanced tree is said to be hidden in a sequence A, if the integers obtained by listing the
weights of all leaves of the tree from left to right form a subsequence of A. Here, a subsequence
is a sequence that can be derived by deleting zero or more elements from the original sequence
without changing the order of the remaining elements.
For instance, the balanced tree in the figure above is hidden in the sequence 3 4 1 3 1 2 4 4 6,
because 4 1 1 2 4 4 is a subsequence of it.
Now, your task is to find, in a given sequence of integers, the balanced tree with the largest
number of leaves hidden in it. In fact, the tree shown in Figure I.1 has the largest number of
leaves among the balanced trees hidden in the sequence mentioned above.
Input
The input consists of multiple datasets. Each dataset represents a sequence A of integers in the
format
N
A1 A2 . . . AN
23
where 1 ≤ N ≤ 1000 and 1 ≤ Ai ≤ 500 for 1 ≤ i ≤ N. N is the length of the input sequence,
and Ai
is the i-th element of the sequence.
The input ends with a line consisting of a single zero. The number of datasets does not exceed
50.
Output
For each dataset, find the balanced tree with the largest number of leaves among those hidden
in A, and output, in a line, the number of its leaves.
Sample Input
9
3 4 1 3 1 2 4 4 6
4
3 12 6 3
10
10 9 8 7 6 5 4 3 2 1
11
10 9 8 7 6 5 4 3 2 1 1
8
1 1 1 1 1 1 1 1
0
Output for the Sample Input
6
2
1
5
8
题意:
给你n个数,让你求出最多叶子的平衡树的叶子有多少。
平衡树:两个相同的数可以合成一个父亲。
题解:
可以知道这个树的和一定是 a ∗ 2 k a*2^k a∗2k,所以我们枚举a,并且a一定是个奇数。之后将所有 a ∗ 2 k a*2^k a∗2k(0<=k<=8)的数都放到数组里面,之后dp找的是所有符合题目条件的序列。dp[j]=max(dp[j],dp[j-b[i]]+1);表示如果有dp[j-b[i]]这个状态,那么当前的b[i]可以和以前的状态合起来。最终再看看2的倍数次的dp中最多的是多少。
#include<bits/stdc++.h>
using namespace std;
int dp[500000],a[1005];
int DP(int num,int b[])
{
int sum=0,maxn=0,po=0;
for(int i=1;i<=num;i++)
sum+=b[i];
while((1<<po)<=sum)
po++;
po--;
maxn=1<<po;
dp[0]=0;
for(int i=1;i<=num;i++)
{
for(int j=maxn;j>=b[i];j-=b[i])
{
if(dp[j-b[i]]!=-1)
dp[j]=max(dp[j],dp[j-b[i]]+1);
}
}
int ans=dp[0];
for(int i=1;i<=maxn;i*=2)
ans=max(ans,dp[i]);
for(int i=1;i<=num;i++)
{
for(int j=maxn;j>=0;j-=b[i])
dp[j]=-1;
}
return ans;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
if(!n)
break;
memset(dp,-1,sizeof(dp));
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int ans=0;
for(int i=1;i<=500;i+=2)
{
int b[1005],ct=0;
for(int j=1;j<=n;j++)
{
if(a[j]%i)
continue;
for(int k=0;k<=8;k++)
{
if((i<<k)==a[j])
b[++ct]=a[j]/i;
}
}
if(ct)
ans=max(ans,DP(ct,b));
}
printf("%d\n",ans);
}
return 0;
}