第四场H-Harder Gcd Problem

Harder Gcd Problem

https://ac.nowcoder.com/acm/contest/5669/H

题意
给出1-n的数字,让选择m对数字,让gcd(a_i,b_i)>1,让m尽可能大,并且输出这m对对应的数字。

思路
整体的思路就是筛法+贪心。
不过我代码写的比较复杂,比较low。。
首先就是筛法,把n个数的质因子种类数,和最小质因数维护出来。cnt[i]表示i的质因子有多少种,mi[i]表示i的最小质因数是多少
开一个vector 其中z[i]表示含有质因子i的数字的集合。
然后我们去进行两个数字的匹配,这里去贪心的选择。
首先我们应该倒序 即从z[n]到z[1]里面去选择。为什么? 因为含有的质因子越大,可以匹配到的另一个的个数越少,所以优先倒序来。
对于具体到某个z[i] 这里还需要一次贪心,比如 z[2][0]=2,z[2][1]=6,z[2][2]=8,z[2][3]=10 对z[2]排序应该是这样的 2 8 10 6
对于一个数的质因子的种类越多,能匹配的个数也越多,所以对于具体的z[i] 应该先按照质因子种类数从小到大排序,对于质因子种类数相同的,最小质因数越大,我们就优先对他进行匹配。
总体复杂度O(T * nlogn)

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
#define int long long
bool vis[maxn];
vector<int> z[maxn],qq;
int cnt[maxn],mi[maxn];
bool cmp(int x,int y){
    if(cnt[x]==cnt[y]) return mi[x]>mi[y];
    return cnt[x]<cnt[y];
}
signed main()
{

    int t;cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        qq.clear();
        for(int i=1; i<=n; i++)
            vis[i]=0,z[i].clear(),cnt[i]=0,mi[i]=1e9;
        for(int i=2;i<=n;i++){
            if(!vis[i]){
                for(int j=i;j<=n;j+=i){
                    vis[j]=1;
                    mi[j]=min(mi[j],i);
                    cnt[j]++;
                    z[i].push_back(j);
                }
            }
        }
        for(int i=1;i<=n;i++) vis[i]=0;
        int ans=0;
        for(int i=n; i; i--)
        {
            sort(z[i].begin(),z[i].end(),cmp);
            int a=-1,b=-1;
            for(int j=0; j<z[i].size(); j++)
            {
                if(!vis[z[i][j]])
                {
                    if(a==-1)
                    {
                        a=z[i][j];
                    }
                    else if(b==-1)
                    {
                        b=z[i][j];
                    }
                }
                if(a!=-1 && b!=-1)
                {
                    qq.push_back(a);
                    qq.push_back(b);
                    ans++;
                    vis[a]=vis[b]=1;
                    a=b=-1;
                }
            }
        }
        cout<<ans<<endl;
        for(int i=0; i<ans; ++i)
            cout<<qq[2*i]<<" "<<qq[2*i+1]<<endl;

    }
    return 0;
}


2020多校 文章被收录于专栏

菜鸡的多校博客题解

全部评论

相关推荐

bg双非本科,方向是嵌入式。这次秋招一共拿到了&nbsp;8&nbsp;个&nbsp;offer,最高年包&nbsp;40w,中间也有一段在海康的实习经历,还有几次国家级竞赛。写这篇不是想证明什么,只是想把自己走过的这条路,尽量讲清楚一点,给同样背景的人一个参考。一、我一开始也很迷茫刚决定走嵌入式的时候,其实并没有一个特别清晰的规划。网上的信息很零散,有人说一定要懂底层,有人说项目更重要,也有人建议直接转方向。很多时候都是在怀疑:1.自己这种背景到底有没有机会2.现在学的东西到底有没有用3.是不是已经开始晚了这些问题,我当时一个都没答案。二、现在回头看,我主要做对了这几件事第一,方向尽早确定,但不把自己锁死。我比较早就确定了嵌入式这个大方向,但具体做哪一块,是在项目、竞赛和实习中慢慢调整的,而不是一开始就给自己下结论。第二,用项目和竞赛去“证明能力”,而不是堆技术名词。我不会刻意追求学得多全面,而是确保自己参与的每个项目,都能讲清楚:我负责了什么、遇到了什么问题、最后是怎么解决的。第三,尽早接触真实的工程环境。在海康实习的那段时间,对我触动挺大的。我开始意识到,企业更看重的是代码结构、逻辑清晰度,以及你能不能把事情说清楚,而不只是会不会某个知识点。第四,把秋招当成一个需要长期迭代的过程。简历不是一次写完的,面试表现也不是一次就到位的。我会在每次面试后复盘哪些问题没答好,再针对性补。三、我踩过的一些坑现在看也挺典型的:1.一开始在底层细节上纠结太久,投入产出比不高2.做过项目,但前期不会总结,导致面试表达吃亏3.早期有点害怕面试,准备不充分就去投这些弯路走过之后,才慢慢找到节奏。四、给和我背景相似的人一点建议如果你也是双非,准备走嵌入式,我觉得有几件事挺重要的:1.不用等“准备得差不多了”再投2.项目一定要能讲清楚,而不是做完就算3.不要只盯着技术,多关注表达和逻辑很多时候,差的不是能力,而是呈现方式。五、写在最后这篇总结不是标准答案,只是我个人的一次复盘。后面我会陆续把自己在嵌入式学习、竞赛、实习和秋招中的一些真实经验拆开来讲,希望能对后来的人有点帮助。如果你正好也在这条路上,希望你能少走一点弯路。
x_y_z1:蹲个后续
点赞 评论 收藏
分享
评论
6
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务