思路:考虑每一个素数对答案的贡献.html
由于一个素数越大,与他匹配的数就会越少,因此考虑优先匹配较大的素数。c++
这样保证每一个含因子是该素数的尽量被匹配到,由于是一组是两个数,因此当知足条件的数的为奇数个时,显然咱们要扔掉一个看是否能和其余数匹配,显然能与最小的质数 匹配的数是最多的,因此咱们保留一下是 的倍数的数,若是已经匹配了奇数个,就直接把它给该素数做为贡献,不然给 的倍数进行匹配。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; }