链接:https://ac.nowcoder.com/acm/contest/5669/H
来源:牛客网

题意:

给你一个1-n的数,让你将n个数分成两堆,且对应的两个数gcd不为1,也就是不互质

solution:

可以从最大的质数k开始往后构造,找出尽可能多的k的奇数倍,如果k的
奇数倍的个数为奇数,就跟2*k进行匹配。然后循环找出前一个最大的质数,最后将2的倍数进行匹配。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
typedef pair<int,int>P;
#define INF 0x3f3f3f3f
int prime[1000005],not_prime[1000005],num=0;
int t,n,mark[2000005];
vector<P> e;
int main()
{
    not_prime[1]=1;
    for(int i=2;i<=200000;i++)
    {
        if(!not_prime[i])
        {
            prime[num++]=i;
            for(int j=2*i;j<=200000;j+=i)
                not_prime[j]=1;
        }
    }
    cin>>t;
    while(t--)
    {
        scanf("%d",&n);
        int k;
        for(int i=0;;i++)
        {
            if(prime[i]<=n/2)k=i;
            else break;
        }
        for(int i=1;i<=n;i++)
            mark[i]=1;
        e.clear();
        //cout<<1;
        for(int i=k;i>0;i--)
        {
            int l=1,r=n/prime[i];
            if(r%2==0)r--;
            //cout<<prime[i]<<endl;
            //cout<<1;
            while(l<=r)
            {
                while(l*prime[i]<=n&&mark[l*prime[i]]==0)
                    l+=2;
                while(r>0&&mark[r*prime[i]]==0)
                    r-=2;
                if(r<=0||l*prime[i]>n)break;
                if(l==r)
                {
                    if(prime[i]*2<=n)
                    {
                        e.push_back(P(prime[i]*2,prime[i]*l));
                        mark[prime[i]*2]=0;
                        mark[prime[i]*l]=0;
                    }
                    break;
                }
                else if(l<r)
                {
                    e.push_back(P(prime[i]*r,prime[i]*l));
                    mark[prime[i]*r]=0;
                    mark[prime[i]*l]=0;
                }
            }
        }
        int l=2,r=n/2*2;
        while(l<r)
        {
            while(l<=n&&mark[l]==0)
                l+=2;
            while(r>0&&mark[r]==0)
                r-=2;
            if(l<r)
            {
                e.push_back(P(r,l));
                mark[r]=0;
                mark[l]=0;
            }
            if(l==r)break;
        }
        printf("%d\n",e.size());
        for(int i=0;i<e.size();i++)
            printf("%d %d\n",e[i].first,e[i].second);
    }
    return 0;
}