Codeforces 1183 F Topforces Strikes Back —— 贪心,因子的性质

This way

题意:

给你一些数,让你找到不超过三个数,其中没有一个数是另一个数的因子,使得这三个数的和最大。

题解:

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;
}

发布了530 篇原创文章 · 获赞 31 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/tianyizhicheng/article/details/103011535
今日推荐