前言
大佬的题解
笔记
理解为动态规划
前提(i, j
a, j > i)(dp[i] 为以i结尾的最大长度)
对于每个i --> j, 方程为 dp[j] = max(dp[j], dp[i] + 1)
每个j 的最大长度只与 i 的最大长度有关
80分代码
没有进行因子分解的
优化,直接枚举导致超时

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int t, n, mx;
const int N = 1e5 + 5;
int a[N], dp[N], ans;
int main()
{
scanf("%d", &t);
while(t--)
{
ans = 1;
scanf("%d", &n);
memset(a, 0, sizeof(a));
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= n; i++)
{
int x;
scanf("%d", &x);
a[x] = 1;
mx = max(mx, x);
}
for(int i = 1; i <= mx; i++)
{
if(a[i]) dp[i] = max(dp[i], 1);
else continue;
int temp = i;
for(int z = 2; z <= temp; z++)
{
if(temp % z == 0)// 找到质因子 开始i->j 的转移
{
for(int j = i + z; j <= mx; j += z)
{
if(a[j]){dp[j] = max(dp[j], dp[i] + 1);ans = max(dp[j], ans); break;}
}
}
else continue;
while(temp % z == 0)
temp /= z;
}
}
cout << ans << endl;
}
return 0;
} #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int t, n, mx;
const int N = 1e5 + 5;
int a[N], dp[N], ans;
int main()
{
scanf("%d", &t);
while(t--)
{
ans = 1;
scanf("%d", &n);
memset(a, 0, sizeof(a));
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= n; i++)
{
int x;
scanf("%d", &x);
a[x] = 1;
mx = max(mx, x);
}
//对于每个优秀的i -> j 转移 条件是 j是i中每个质因子的最小倍数
//状态转移方程 (dp[j] = max dp[i] + 1)
// 1.枚举i 找质因子
// 2. 找到j转移
for(int i = 1; i <= mx; i++)
{
if(a[i]) dp[i] = max(dp[i], 1);
else continue;
int temp = i;
for(int z = 2; z * z <= temp; z++)
{
if(temp % z == 0)// 找到质因子 开始i->j 的转移
{
for(int j = i + z; j <= mx; j += z)
{
if(a[j]){dp[j] = max(dp[j], dp[i] + 1);ans = max(dp[j], ans); break;}
}
}
else continue;
while(temp % z == 0)
temp /= z;
}
if(temp > 1))//剩下了个大于根号的质数
{
for(int j = i + temp; j <= mx; j += temp)
{
if(a[j]){dp[j] = max(dp[j], dp[i] + 1);ans = max(dp[j], ans); break;}
}
}
}
cout << ans << endl;
}
return 0;
}