【2020牛客多校第四场 H题】Harder Gcd Problem

Harder Gcd Problem

题意

给出 n 个数字1 2 3 .... n ,让构造出两个集合 A,B ,满足以下条件:

  1. A ∩ B == ∅ and | A | == | B | == m
  2. \(gcd(A_i,B_i) > 1\)

思路

按照每个数字的最小质因子分组。

2:

3:

5:

7:

...

初始一直想的是从 2组开始,组中每两个作为一对输出,如果有奇数个数字,那么将最后一个数字除完所有的 2 ,将其放到次小质因子组中去。就这样一直遍历。然后直接找出了反例。。。

然后就想着改进,但是想出的方法都给人一种不完美的感觉。

题解

从 3 开始进行,如果当前组的数字个数为奇数,那么从 2 组中判断是否有最小数字的 2 倍,如果有那么这俩数字作为一对,其他相邻的作为一对。

就是把 2组中的数字当做备选,最后 2 组再自行匹配。

代码

#include <bits/stdc++.h>
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int N = 1e6 + 10;

int vis[N],pri[N],tot;
void solve(int n)
{
    for(int i=2; i<=n; i++)
    {
        if(!vis[i])
            pri[++tot]=i;
        for(int j=1; j<=tot; j++)
        {
            if(i*pri[j]>n)
                break;
            vis[i*pri[j]]=pri[j];//纪录最小的素因子
            if(i%pri[j]==0)
                break;
        }
    }
}

vector<int>vec[N];
vector<pair<int,int> >ans;
int sign[N];
int main()
{
    solve(200005);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
            vec[i].clear();
        ans.clear();
        for(int i=2; i<=n; i++)
        {
            if(vis[i]==0) vis[i]=i;
            sign[i]=0;
            vec[vis[i]].pb(i);
        }
        for(int i=3;i<=n;i++)
        {
            if(vec[i].size()%2){
                for(int j=1;j+1<vec[i].size();j+=2)
                    ans.pb(make_pair(vec[i][j],vec[i][j+1]));
                if(sign[vec[i][0]*2]==0&&2*vec[i][0]<=n){
                    ans.pb(make_pair(vec[i][0],vec[i][0]*2));
                    sign[vec[i][0]*2]=1;
                }
            }
            else{
                for(int j=0;j+1<vec[i].size();j+=2){
                    ans.pb(make_pair(vec[i][j],vec[i][j+1]));
                }
            }
        }
        int pre=0;
        for(int v:vec[2]){
            if(sign[v]==0){
                if(pre==0) pre=v;
                else
                {
                    ans.pb(make_pair(pre,v));
                    pre=0;
                }
            }
        }
        printf("%d\n",ans.size());
        for(auto now:ans){
            printf("%d %d\n",now.first,now.second);
        }
    }
    return 0;
}
posted @ 2020-07-21 19:52  Valk3  阅读(174)  评论(0编辑  收藏  举报