E. Jzzhu and Apples
time limit per test: 1 seconds
memory limit per test: 256 megabytes
input: standard input
output: standard output
Jzzhu has picked \(n\) apples from his big apple tree. All the apples are numbered from \(1\) to \(n\). Now he wants to sell them to an apple store.
Jzzhu will pack his apples into groups and then sell them. Each group must contain two apples, and the greatest common divisor of numbers of the apples in each group must be greater than \(1\). Of course, each apple can be part of at most one group.
Jzzhu wonders how to get the maximum possible number of groups. Can you help him?
Input
A single integer \(n (1?≤?n?≤?10^5)\), the number of the apples.
Output
The first line must contain a single integer \(m\), representing the maximum number of groups he can get. Each of the next m lines must contain two integers — the numbers of apples in the current group.
If there are several optimal answers you can print any of them.
input
6
output
2
6 3
2 4
input
9
output
3
9 3
2 4
6 8
input
2
output
0
题意
给出正整数\(n\),求出\(\left[1,n\right]\)之间的正整数有多少对数字的最大公约数不等于\(1\),输出最多的组数,并按任意顺序输出这些数字
思路
要使\(gcd(x,y)>1\),那么\(x,y\)中的较小的数一定不大于\(n/2\),所以我们首先筛出来\([1,n/2]\)范围内的素数
筛出来素数之后,每次在取数的时候,要保证取完数之后,不会使总的符合要求的数对减少,所以我们从最大的素数(假设为\(x\))开始枚举,能够整除\(x\)的整数一定使最少的,而且不会影响到别的数对(感性理解一下:因为枚举到了\(n/2\),所以\(n/x<=3\),\(2\)的倍数还是很多的减少一个没什么影响,\(n/x=3\)时,大概只有\(n=9\)的时候,那么也是不会产生影响的)
然后去统计当前素数\(p\)的倍数个数\(num\),如果\(num\)是偶数,直接匹配(为了简便,就相邻的两个数组成一对)
如果\(num\)是奇数,我们可以将\(p\)的\(2\)倍和\(num\)倍交换位置,这样匹配完剩下的那个数可以去和\(2\)的倍数来匹配,这样可以达到最优
代码
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define ms(a,b) memset(a,b,sizeof(a))
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=1e6+10;
const int mod=1e9+7;
const int maxm=1e3+10;
using namespace std;
int vis[maxn];
int prime[maxn];
int cnt;
int a[maxn];
void get_prime(int n)
{
vis[0]=vis[1]=1;
for(int i=2;2*i<=n;i++)
if(!vis[i])
for(int j=2;j*i*2<=n;j++)
vis[j*i]=1;
for(int i=2;2*i<=n;i++)
if(!vis[i])
prime[cnt++]=i;
}
int main(int argc, char const *argv[])
{
#ifndef ONLINE_JUDGE
freopen("/home/wzy/in", "r", stdin);
freopen("/home/wzy/out", "w", stdout);
srand((unsigned int)time(NULL));
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin>>n;
get_prime(n);
ms(vis,0);
vector<pair<int,int> >ve;
for(int i=cnt-1;i>=0;i--)
{
int tot=0;
for(int j=prime[i];j<=n;j+=prime[i])
if(!vis[j])
a[++tot]=j;
// 如果倍数有奇数个,交换第二个和最后一个
if(tot&1)
swap(a[2],a[tot]);
for(int j=1;j+1<=tot;j+=2)
{
vis[a[j]]=vis[a[j+1]]=1;
ve.push_back({a[j],a[j+1]});
}
}
cout<<ve.size()<<endl;
for(auto i:ve)
cout<<i.first<<" "<<i.second<<endl;
#ifndef ONLINE_JUDGE
cerr<<"Time elapsed: "<<1.0*clock()/CLOCKS_PER_SEC<<" s."<<endl;
#endif
return 0;
}