1599. 【GDKOI2004】香樟树

  1. 【GDKOI2004】香樟树

题目描述

被誉为江南四大名木之一的香樟树很有特色,它的树皮粗糙,质地却很均匀,从来没有白杨树的斑斑驳驳、没有柳树的肿瘤结节;树枝树干一分为二、二分为四一路长去,不会偷工减料也不会画蛇添足;树冠的形态是球形的,在天空中画出优美的曲线。

除了上述优点之外,香樟树还有一个秘密武器。那就是……………………它凭借朴实、厚重的优秀品格赢得了小狐狸的青睐!!!

话说有一天,小狐狸正在湖边散步,忽然一阵风吹来,她赶紧闭上眼睛。当她再次睁开眼睛时,发现美丽的湖畔多出了一排整齐的香樟树。小狐狸非常兴奋,她对每棵树都观察入微,并且数出了它们的叶子个数。她觉得如果相邻两棵树的叶子个数互素是不和谐的。因此小狐狸想从一排香樟树中选出若干棵,在满足相邻两棵树的叶子个数不互素的条件下,使得树尽量多。

输入

第一行一个正整数n,表示有n棵香樟树。

第二行n个正整数,第i个数表示第i棵香樟树叶子的个数。

输出

一个正整数,表示最多能选多少棵树。

样例输入

6
6 2 3 15 8 5

样例输出

4

数据范围限制

提示

注释 Hint

样例解释:选择第1、第3、第4和第6棵树

数据范围,对于60%的数据n<=1000

     对于100%的数据 n<=100000,叶子个数<=100000

注意:选中的树不能改变其位置,即如果选中第(t1,t2,t3……tn)棵树 ,其中t1 < t2 < t3< …… < tn则认为ti与ti+1相邻。

方法:

1,用类似最长不下降子序列的方法(n^2)做,最高60分(时超);

2,(水法,不推荐)j循环可优化至log(n)*2-n;

为什么?

看数据大法!(数据很无辜)

3,正解,dp。

没错,就是dp。

先用筛法求出素数,1-100000的。

(9592个)

设f[i]为i的最大答案。

将每一个a[i]分解质因数,存在ll数组中。

f[i]=max(r[ll[i]])+1;

r[ll[i]]=f[i];

至此完结。

代码

请勿抄袭

var
        i,j,k,m,n,o,p,l,s,t:longint;
        a:array[1..100000] of longint;
        f,r:array[1..100000] of longint;
        pri:array[0..9592] of longint;
        ll:array[0..100000] of longint;
function max(a,b:longint):longint;
begin
        if a>b then exit(a) else exit(b);
end;
begin
        assign(input,'camphor.in');reset(input);
        assign(output,'camphor.out');rewrite(output);
        readln(n);
        for i:=1 to n do read(a[i]);
        for i:=2 to 10000 do
        begin
                s:=0;
                for j:=2 to trunc(sqrt(i)) do begin
                        if i mod j=0 then begin
                                s:=1;
                                break;
                        end;
                end;
                if s=0 then begin
                        inc(pri[0]);
                        pri[pri[0]]:=i;
                end;
        end;
        for i:=1 to n do begin
                k:=a[i]; ll[0]:=0;
                for j:=1 to pri[0] do begin
                        if k mod pri[j]=0 then begin
                                inc(ll[0]);ll[ll[0]]:=pri[j];
                                repeat
                                        k:=k div pri[j];
                                until k mod pri[j]<>0;
                        end;
                        if k=1 then break;
                end;
                for j:=1 to ll[0] do begin
                        f[i]:=max(r[ll[j]],f[i]);
                end;
                f[i]:=f[i]+1;
                for j:=1 to ll[0] do begin
                        r[ll[j]]:=f[i];
                end;
        end;
        for i:=1 to 100000 do
                s:=max(s,f[i]);
        writeln(s);
        close(input);close(output);
end.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值