1. 程式人生 > 實用技巧 >【2020牛客多校第四場 H題】Harder Gcd Problem

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