题意:给你一组数然后统计他们之中能组成两两互为倍数的数最多有多少个?
思路:考虑DP,dp[i]代表值当前选的数都为i的约数的最大的个数是多少,我们当然可以暴力的用每个i去更新它的倍数,但是这样做会超时,我们可以用素数去更新它的倍数,素数筛的优化一样,省去很多不必要的更新,然后每次取下max就是答案了。
dp[i]的初始化为i这个数在原序列中出现的次数。
素数问题做少了,还要多练习数学思维啊
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e7 + 7;
int prime[MAXN],vis[MAXN],cnt;
void work(){
for(int i = 2;i < MAXN;i ++){
if(!vis[i]) prime[++cnt] = i;
for(int j = 1;j <= cnt && prime[j] * i < MAXN;j ++){
vis[prime[j]*i] = 1;
if(i % prime[j] == 0)
break;
}
}
}
int dp[MAXN],num[MAXN];
int main()
{
work();
int n,x;
scanf("%d",&n);
for(int i = 1;i <= n;i ++){
scanf("%d",&x);
num[x]++;
}
int ans = 0;
for(int i = 1;i < MAXN;i ++){
dp[i] += num[i];
ans = max(ans,dp[i]);
for(int j = 1;j <= cnt && prime[j] * i < MAXN;j ++){
dp[prime[j]*i] = max(dp[prime[j]*i],dp[i]);
}
}
printf("%d\n",ans);
return 0;
}