小L的数列
比赛主页
我的提交
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld
题目描述
小L喜欢数和数列。小L称a_1…a_na
1
…a
n
这些数为优秀的。小L称一个序列b_1…b_mb
1
…b
m
为好的当且仅当:
1.对于任意的 i (1 \leq i <m)i(1≤i<m),满足 b_i<b_{i+1}b
i
<b
i+1
。
2.对于任意的 i (1 \leq i <m)i(1≤i<m),满足 gcd(b_i,b_{i+1})>1gcd(b
i
,b
i+1
)>1。其中,gcd(x,y)gcd(x,y) 为 xx 和 yy 的最大公因数,即最大的 dd,满足:d|xd∣x且d|yd∣y。
3.对于任意的 i (1 \leq i \leq m)i(1≤i≤m),b_ib
i
这个数是优秀的。
现在,小L想知道最长的能称为好的的序列的长度是多少,容易证明这个长度是有穷的。
输入描述:
有多组测试点,输入第一行一个数T表示测试点的个数。
对于每一个测试点有两行:
第一行一个正整数 nn,表示优秀的数的个数
第二行 nn 个整数 a_1 … a_na
1
…a
n
,表示小 L 称为优秀的数,保证 a_ia
i
两两不相同。
输出描述:
输出共 TT 行,每一行为一个测试点的答案,即最长的好的序列的长度。
示例1
输入
复制
2
5
4 6 3 2 9
9
10 2 5 3 6 9 7 8 1
输出
复制
4
4
说明
对于第一个测试点来说,一个最长的好的序列可以是 [2, 4, 6, 9],长度为 4 。容易看出没有更长的好的序列。
对于第二个测试点来说,一个最长的好的序列可以是[3, 6, 8, 10],长度为 4 。容易看出没有更长的好的序列。
对于 30%30% 的数据,满足 n, a_i \leq 10n,a
i
≤10。
对于 60%60% 的数据,满足 n, a_i \leq 1000n,a
i
≤1000。
另有 20%20% 的数据,满足n \leq 1000n≤1000。
对于 100%100% 的数据,满足 2 \leq n \leq 100000, 1 \leq a_i \leq 100000, T \leq 5, a_i2≤n≤100000,1≤a
i
≤100000,T≤5,a
i
两两不同。
首先gcd(x,y)>1也就是说他们有相同的大于1的质因子
对于x<y<z,他们都有相同的质因子,那么x和z肯定不相邻。
这句话的意思是当我们拓展这个数的其中一个质因子时,我们只需要枚举到第一个大于它且具有同一个质因子的数即可。
dp[i]表示当前的数为i时的最大合法长度。
#include<iostream>
#include<math.h>
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000000
int dp[maxn];
int a[maxn];
int main()
{
int t;
cin>>t;
while(t--)
{ memset(dp,0,sizeof dp);
memset(a,0,sizeof a);
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
a[x]=1;
}
int ans=0;
for(int i=1;i<=100000;i++)
{
int t=i;
if(a[i])//如果当前数存在
{
dp[i]=max(dp[i],1);//更新dp【i】
ans=max(dp[i],ans);//更新答案
}
else
continue;
for(int j=2;j*j<=100000;j++)//枚举质因数
{
if(t%j==0)
{
for(int k=i+j;k<=100000;k+=j)
{
if(a[k])//如果当前数存在
{
dp[k]=max(dp[k],dp[i]+1);//看是由i到k大,还是其他方式大。
break;
}
}
}
while(t%j==0)
t/=j;
}
if(t>1)//有一个大于1的根号
{
int j=t;
for(int k=j+i;k<=100000;k+=j)
{
if(a[k])
{
dp[k]=max(dp[k],dp[i]+1);
break;
}
}
}
}
cout<<ans<<endl;
}
}