【广州市选2014】Tree(tree)

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= 2xy 这样的形式,所以我们可以先枚举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.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值