2020牛客暑期多校训练营(第四场)H题Harder Gcd Problem(贪心)
2020牛客暑期多校训练营(第四场)H题Harder Gcd Problem(贪心)
题意:从n中取m对数,使每对数的gcd不为1,输出最大的m与方案;
题解:从最大的质因数往下枚举,如果为其倍数并且没用过的个数为偶数,则互相连接,如果为奇数个且大于1,将任意一个质因数的偶数倍的一个数的改为没用过(这里留一个偶数是留个最小的质因数2用),将其他数相互连接。
#include<iostream>
#include<vector>
using namespace std;
const int N=2e5+7;
int t,n,vis[N];
vector<int>G[N],ho,sa;
vector<pair<int,int > >ans;
bool isnot[N];
void getys(){
for(int i=2;i<N;i++){
if(!isnot[i]) {
for (int j = i; j < N; j += i) {
isnot[j] = true;
G[i].push_back(j);
}
}
}
}
int main(){
getys();
scanf("%d",&t);
while(t--){
ans.clear();
scanf("%d",&n);
for(int i=1;i<=n;i++)vis[i]=0;
for(int i=n/2;i>=2;i--){
ho.clear();
if(G[i].size()==0)continue;
for(int j=0;j<G[i].size();j++){
if(G[i][j]>n)continue;
if(!vis[G[i][j]]){
vis[G[i][j]]=1;
ho.push_back(G[i][j]);
}
}
if(ho.size()%2==0){
for(int j=0;j<ho.size();j+=2){
ans.push_back({ho[j],ho[j+1]});
}
}
else{
int ok=0;
sa.clear();
for(int j=0;j<ho.size();j++){
if(ho[j]%2==0&&!ok){
vis[ho[j]]=0;
ok=1;
}
else{
sa.push_back(ho[j]);
}
}
for(int j=0;j<sa.size();j+=2){
ans.push_back({sa[j],sa[j+1]});
}
}
}
printf("%d\n",ans.size());
for(int i=0;i<ans.size();i++){
printf("%d %d\n",ans[i].first,ans[i].second);
}
}
}