标签:比较 复杂 小数 线性 cto 质数 几句话 注意 ret
const int MAXN=100005;
int n,m,ans;
int a[MAXN],v[MAXN],pri[MAXN],f[MAXN];
vector<int> q[MAXN];
//q[i]记录的是序列a中所有能被i整除的数的下标
//线性筛素数
void get_prime(){
v[1]=1;
for(int i=2;i<=MAXN;i++){
if(!v[i]){
pri[++m]=i;
v[i]=i;
}
for(int j=1;j<=m;j++){
if(pri[j]>v[i]||i*pri[j]>MAXN)
break;
v[i*pri[j]]=pri[j];
}
}
}
int main(){
get_prime();
n=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=n;i++){//枚举序列a
int now=a[i];
for(int j=1;j<=m;j++){//枚举所有质数
if(now%pri[j]==0){
//如果now能够被pri[j]整除,a[i]肯定也能被pri[j]整除
while(now%pri[j]==0)now/=pri[j];
//这里与下面代码中if(now<pri[j])break;相照应
//是为了优化时间
int cnt=q[pri[j]].size();
if(cnt)f[i]=max(f[i],f[q[pri[j]][cnt-1]]+1);
//如果cnt不为零,即之前已经存在a[k]能够被pri[j]整除
//则f[i]可以从q[pri[j]]中的最后一个数转移
else f[i]=max(f[i],1);
//否则,说明之前枚举的所有的a[k]
//与当前的a[i]的共同的质因子不包括pri[j]
//即f[i]无法从前面转移过来
q[pri[j]].push_back(i);
//既然当前的a[i]能被pri[j]整除,就可以更新q[pri[j]]
}
if(now<pri[j])break;
//如果now已经比当前的pri[j]小,
//pri数组里的质数肯定是单调递增的,
//后面就更不会有比now还小的质数了,
//即后面肯定不存在j,使得now%pri[j]=0了,直接退出
}
}
for(int i=1;i<=n;i++)ans=max(ans,f[i]);
if(!ans)puts("1");//序列只有一个数显然成立
else printf("%d\n",ans);
return 0;
}
标签:比较 复杂 小数 线性 cto 质数 几句话 注意 ret
原文地址:https://www.cnblogs.com/PPXppx/p/10371558.html