2020牛客暑期多校第四场-H Harder Gcd Problem(贪心构造)

题目大意:给你一个序列1-n,你要找到尽可能多的匹配使得每个匹配值的gcd>1,输出匹配的个数和每个匹配

输入

2
4
10

输出

1
2 4
4
3 9
5 10
8 2
4 6

emmm,这题的话应该还是感觉比较好写的,先将素数筛出了,对每个素数p的点放入p,2p,3p,4p...kp(kp<=n),那么里面的数就可以任意匹配了,那么对于2这个素数我们先不急,我们先将3到n/2以内的素数的内容放好,对于每个素数的size,如果里面是偶数的话我们就任意匹配,如果是奇数的话,我们将2p保留下来,放入到2的内容中,剩余的任意匹配,最后我们再出来2这个值就好了。

以下是AC代码:

#include <bits/stdc++.h>
using namespace std;

#define debug printf("@#$#@%")
const int mac=2e5+10;

int vis[mac];
vector<int>prim[mac];
int vs[mac],val[mac];

int main(int argc, char const *argv[])
{
    int t,n;
    scanf ("%d",&t);
    for (int i=2; i<=sqrt(mac); i++)
        if (!vis[i]) 
            for (int j=i*i; j<mac; j+=i)
                vis[j]=1;
    int cnt=0;
    for (int i=2; i<mac; i++)
        if (!vis[i]) val[++cnt]=i;
    while (t--){
        int n;
        scanf ("%d",&n);
        for (int i=1; i<=n; i++) vs[i]=0;
        for (int i=1; 2*val[i]<=n; i++) prim[i].clear(),prim[i].push_back(val[i]);
        prim[1].push_back(4);
        vector<pair<int,int>>ans;
        for (int i=2; 2*val[i]<=n; i++){
            for (int j=2*val[i]; j<=n; j+=val[i]){
                if (vs[j]) continue;            
                prim[i].push_back(j);
                vs[j]=1;
            }
            if ((prim[i].size()&1) && prim[i].size()>1){
                ans.push_back(make_pair(prim[i][0],prim[i][2]));
                for (int j=3; j<prim[i].size(); j+=2){
                    ans.push_back(make_pair(prim[i][j],prim[i][j+1]));
                }
                prim[1].push_back(prim[i][1]);
            }
            else {
                for (int j=0; j<prim[i].size(); j+=2)
                    ans.push_back(make_pair(prim[i][j],prim[i][j+1]));
            }
            prim[i].clear();
        }
        for (int j=2*3; j<=n; j+=2){
            if (vs[j]) continue;
            prim[1].push_back(j);
        }
        if ((prim[1].size()&1)) 
            for (int i=1; i<prim[1].size(); i+=2)
                ans.push_back(make_pair(prim[1][i],prim[1][i+1]));
        else 
            for (int i=0; i<prim[1].size(); i+=2)
                ans.push_back(make_pair(prim[1][i],prim[1][i+1]));
        printf ("%d
",ans.size());
        for (int i=0; i<ans.size(); i++)
            printf("%d %d
",ans[i].first,ans[i].second);
    }
    return 0;
}
路漫漫兮
原文地址:https://www.cnblogs.com/lonely-wind-/p/13348265.html