Description
从 (1..n) 中找两个不交的,大小分别为 (m) 的集合,它们存在一种配对方式,使得每对的最大公约数大于 (1)。求最大的 (m)。
Solution
降序枚举所有质数,找到所有未被使用的它的倍数
若有偶数个则两两配对,若有奇数个则将 (2p) 留下来
所有大于 (n/2) 的质数和 (1) 都无法被配对
若其余的数有偶数个,则算法执行后没有剩余
若其余的数有奇数个,则算法执行后剩余 (1) 个数
故为一种最优解
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 200005;
int isp[N],a[N],n,t;
signed main()
{
ios::sync_with_stdio(false);
for(int i=2;i<N;i++)
{
isp[i]=1;
for(int j=2;j*j<=i;j++)
{
if(i%j==0)
{
isp[i]=0;
break;
}
}
}
cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=n;i++) a[i]=1;
vector <pair<int,int>> ans;
for(int i=n/2;i>=2;--i)
{
if(isp[i])
{
vector<int> vec;
for(int j=i;j<=n;j+=i)
{
if(a[j])
{
vec.push_back(j);
}
}
if(vec.size()&1)
{
for(int j=0;j<vec.size();j++)
{
if(vec[j]==i*2) vec.erase(vec.begin()+j);
}
}
for(int j=1;j<vec.size();j+=2)
{
ans.push_back({vec[j],vec[j-1]});
a[vec[j]]=0;
a[vec[j-1]]=0;
}
}
}
cout<<ans.size()<<endl;
for(int i=0;i<ans.size();i++) cout<<ans[i].first<<" "<<ans[i].second<<endl;
}
}