题意:
给你一些数,让你找到不超过三个数,其中没有一个数是另一个数的因子,使得这三个数的和最大。
题解:
for一遍,用一个set保存已经存有的数,每次暴力的消除这个数的所有因子,然后再找到最大的数,在消除那个数的因子,找到之后剩下的最大的数。为什么可以贪心的去做,假设我现在是x,y,z三个数,为什么找到一个最大的y,而不是选择一个小一点的y1,因为如果选择小一点的,那么是因为z是y的因子,同时y1是y的因子,那么两个因子的和必然小于等于这个数,所以不如取y。
那么为什么可以暴力消除呢,因为我们假设现在有n个数,这n个数的所有因子的数量级是nlogn的,因为1的倍数有n个,2的倍数有n/2个,3的有n/3个。。。这样加起来是nlogn
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
vector<int>vec[N];
unordered_map<int,bool>mp;
set<int,greater<int> >s;
int a[N];
int main()
{
for(int i=1;i<N;i++)
for(int j=i;j<N;j+=i)
vec[j].push_back(i);
int t;
scanf("%d",&t);
while(t--)
{
mp.clear();
s.clear();
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
sort(a+1,a+1+n);
int all=unique(a+1,a+1+n)-a-1;
int ans=a[all];
for(int i=1;i<=all;i++)
{
for(auto j:vec[a[i]])
s.erase(j);
mp[a[i]]=1;
if(!s.empty())
{
int x=*s.begin();
ans=max(ans,a[i]+x);
for(auto j:vec[x])
s.erase(j);
if(!s.empty())
ans=max(ans,a[i]+x+*s.begin());
for(auto j:vec[x])
if(mp.count(j))
s.insert(j);
}
for(auto j:vec[a[i]])
if(mp.count(j))
s.insert(j);
}
printf("%d\n",ans);
}
return 0;
}