Harder Gcd Problem(贪心)

Harder Gcd Problem(贪心)

思路:考虑每一个素数对答案的贡献.html

由于一个素数越大,与他匹配的数就会越少,因此考虑优先匹配较大的素数。c++

这样保证每一个含因子是该素数的尽量被匹配到,由于是一组是两个数,因此当知足条件的数的为奇数个时,显然咱们要扔掉一个看是否能和其余数匹配,显然能与最小的质数 2 2 匹配的数是最多的,因此咱们保留一下是 2 2 的倍数的数,若是已经匹配了奇数个,就直接把它给该素数做为贡献,不然给 2 2 的倍数进行匹配。web

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
int p[N],n,t,cnt,ans[N],tot;
bool a[N],vis[N];
void pre(){
    int n=2e5;
    for(int i=2;i<=n;i++){
        if(!a[i]) p[cnt++]=i;
        for(int j=0;j<cnt&&i*p[j]<=n;j++){
            a[i*p[j]]=true;
            if(i%p[j]==0) break;
        }
    }
}
int main(){
    pre();
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);tot=0;
        for(int i=1;i<=n;i++) vis[i]=0;
        int pos=upper_bound(p,p+cnt,n/2)-p-1;
        for(int i=pos;~i;i--){
            for(int j=p[i];j<=n;j+=p[i]){
                if(vis[j]||j==(p[i]<<1)) continue;
                ans[++tot]=j,vis[j]=1;
            }
            if(tot&1) vis[(p[i]<<1)]=1,ans[++tot]=(p[i]<<1);
        }
        printf("%d\n",tot>>1);
        for(int i=1;i<=tot;i+=2) printf("%d %d\n",ans[i],ans[i+1]);
    }
    return 0;
}