- 【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.