给一个数 n n n,小于 n n n的公因数大于1的两个数可以组合在一起,求最多有多少组数。
构造:从小于 n n n的最大素数 p p p开始,尽量将 p p p的倍数组合在一起,如果 p p p的倍数的个数为偶数,则将 2 × p 2\times p 2×p留下,直到 p = 2 p=2 p=2时将这个数用上。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define mem(ss) memset(ss,0,sizeof(ss))
#define rep(d, s, t) for(int d=s;d<=t;d++)
#define rev(d, s, t) for(int d=s;d>=t;d--)
#define inf 0x3f3f3f3f
typedef long long ll;
typedef long double ld;
typedef double db;
typedef std::pair<int, int> pii;
typedef std::pair<ll, ll> pll;
const ll mod = 1e9 + 7;
const int N = 2e5 + 10;
#define io_opt ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }
int T, n;
int pri[N], tot=0, mp[N];
inline void sieve() {
mp[1] = 1;
for (int i = 2; i <= N; i++) {
if (!mp[i]) pri[++tot] = i;
for (int j = 1; j <= tot && i * pri[j] <= N; j++) {
mp[i * pri[j]] = 1;
if (i % pri[j] == 0) break;
}
}
}
int hashv[N];
int main() {
sieve();
cin >> T;
while (T--) {
mem(hashv);
vector<pii> ans;
cin >> n;
int k = upper_bound(pri+1,pri+tot+1,n)-pri-1;
for(int i=k;i>=1;i--){
int cnt=0,t=(n/pri[i])*pri[i];
queue<int> q;
q.push(pri[i]);
while(t>pri[i]){
if(!hashv[t]) q.push(t);
t-=pri[i];
}
while(q.size()>=2){
int f1=q.front();q.pop();
int f2=q.front();q.pop();
ans.push_back(pii(f1,f2));
hashv[f1]=hashv[f2]=1;
}
}
cout << ans.size()<<endl;
for(pii x:ans){
cout << x.first <<' '<<x.second << endl;
}
}
return 0;
}