Description
下图展示了一种二叉树:
这种二叉树的每个叶子节点上都标注了权值,而且具有以下有趣的特性:每个非叶子节点,其左右子树叶子节点的权值之和相等。我们称这种二叉树叫平衡二叉树。
我们将一棵平衡二叉树叶子节点的权值从左到右列出来,假如这个权值序列是另一个序列A的子序列,我们称这棵平衡二叉树“隐藏”在序列A当中。在本题中,我们称一个序列S2是另一个序列S1的子序列,当且仅当S2可以由S1中删除0个或多个元素,但不改变S1中剩余元素的相对位置获得。
例如,上图中的平衡二叉树隐藏在序列3 4 1 3 1 2 4 4 6中,因为4 1 1 2 4 4是该序列的子序列。
你的任务是对给定的整数序列,寻找当中隐藏的具有最多叶子节点的平衡二叉树。
Input
输入的第一行是一个正整数n(n<=1000),分别序列的元素数目,第二行是用空格分隔的n个整数ai(1<=i<=n,1<=ai<=500)代表了该序列的第i个元素。
Output
输出只有一个整数,代表该序列当中隐藏的具有最多叶子节点的平衡二叉树的叶子节点总数。
Sample Input
输入1:
9
3 4 1 3 1 2 4 4 6
输入2:
4
3 12 6 3
输入3:
10
10 9 8 7 6 5 4 3 2 1
输入4:
11
10 9 8 7 6 5 4 3 2 1 1
输入5:
8
1 1 1 1 1 1 1 1
Sample Output
输出1:
6
输出2:
2
输出3:
1
输出4:
5
输出5:
8
Data Constraint
n<=1000,1<=ai<=500
题解
我们设fx表示现在取的值和为x,最多可以取fx个数
可以发现选的数都满足 ai=
2x∗y
这样的形式,所以我们可以先枚举y然后找到每次合法的ai
然后fx=max(f[x],f[x-ai]),这条方程式在ai|x的时候可以转移
还要卡一下常数才可以过
贴代码
var
f:array[0..500005]of longint;
a:array[0..1005]of longint;
bz:array[0..1005]of boolean;
i,j,k,l,n,m,x,y,z,ans,maxx,macc:longint;
b:boolean;
begin
assign(input,'tree.in'); reset(input);
assign(output,'tree.out'); rewrite(output);
readln(n);
for i:=1 to n do read(a[i]);
readln;
for z:=1 to 500 do
begin
maxx:=0;
macc:=0;
if b then fillchar(f,sizeof(f),0);
b:=false;
for i:=1 to n do
if (bz[i]=false) and (a[i] mod z=0) and ((a[i] div z)=(a[i] div z) and -(a[i] div z)) then
begin
b:=true;
//x:=a[i] div z;
//if (bz[i]=true) or (a[i] mod z<>0) or (x<>x and -x) then continue;
for j:=maxx downto 0 do
if j mod a[i]=0 then break;
while j>=0 do
begin
if (j<>0) and (f[j]=0) then
begin
j:=j-a[i];
continue;
end;
x:=j+a[i];
if f[x]<f[j]+1 then f[x]:=f[j]+1;
if x>macc then macc:=x;
x:=x div z;
if (x=x and -x) and (f[j+a[i]]>ans) then ans:=f[j+a[i]];
j:=j-a[i];
end;
maxx:=macc;
bz[i]:=true;
end;
end;
writeln(ans);
close(input); close(output);
end.