题意:
每组两个数
数据范围:n<=2e5
解法:
原题:Codeforces449 C. Jzzhu and Apples(一模一样)
如果是奇数个,留下一个偶数就行了(2p或者2p的倍数)
因为一个质数p1多出来的偶数可以和另一个质数p2多出来的偶数匹配,这样能更大
我代码是奇偶分类,优先配对奇数,然后再偶数
-----分割线-----
显然1不参与配对,2p>n的质数n也不参与配对
对于每个数x,预处理出最大质因子,根据最大质因子分成若干等价类,
每个等价类互相配对,如果是奇数个,则保留出一个偶数出来,
因为不同等价类多出来的偶数可以两两配对,这样对数更多。
题解中倒序枚举和取最大质因子,两者的思想是类似的。
code:
#include<bits/stdc++.h>
using namespace std;
const int maxm=2e5+5;
int mark[maxm];
//
int notprime[maxm];
int prime[maxm],cnt;
void init1(){
for(int i=2;i<maxm;i++){
if(!notprime[i]){
prime[cnt++]=i;
}
for(int j=0;j<cnt;j++){
if(1LL*prime[j]*i>=maxm)break;
notprime[prime[j]*i]=1;
if(i%prime[j]==0)break;
}
}
}
//
vector<pair<int,int> >ans;
vector<int>temp[2];
signed main(){
init1();
ios::sync_with_stdio(0);
int T;cin>>T;
while(T--){
ans.clear();
int n;cin>>n;
for(int i=1;i<=n;i++){
mark[i]=0;
}
for(int i=n;i>=2;i--){
if(notprime[i])continue;
temp[0].clear();
temp[1].clear();
int x=i;
for(int j=x;j<=n;j+=x){
if(!mark[j]){
temp[j%2].push_back(j);//奇偶分类
}
}
int last=-1;
for(int v:temp[1]){//先匹配奇数
if(last!=-1){
ans.push_back({last,v});
mark[v]=mark[last]=1;
last=-1;
}else{
last=v;
}
}
for(int v:temp[0]){//然后匹配偶数
if(last!=-1){
ans.push_back({last,v});
mark[v]=mark[last]=1;
last=-1;
}else{
last=v;
}
}
}
cout<<ans.size()<<endl;
for(auto i:ans){
cout<<i.first<<' '<<i.second<<endl;
}
}
return 0;
}