先是官方题解:
Firstly, we should notice that 1 and the primes larger than N / 2 can not be matched anyway, so we ignore these numbers.
Let's consider each prime P where 2 < P ≤ N / 2. For each prime P, we find all of the numbers which are unmatched and have a divisor P. Let M be the count of those numbers we found. If M is even, then we can match those numbers perfectly. Otherwise, we throw the number 2P and the remaining numbers can be matched perfectly.
Finally, only even numbers may be unmatched and we can match them in any way.
这道题做了挺久了,今天纠结于另外一道题,想想还是先回顾一下= =。这道题没看题解前确实没什么思路,主要是每次看到好像和数论相关的就会吓住,其实这种题主要是思维性的,和知识关联并不大。主要这道题记录下来是线性筛素数每次还得去网上找模板,其实挺简单的,多用几次就熟练了。这道题解什么的官方题解写的很清楚,没什么好说的了。#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <deque>
using namespace std;
const int maxn = 100010;
#define MAX 100000
int prime[maxn],cnt,vis[maxn];
void init_prim()
{
memset(vis,0,sizeof(vis));
cnt = 0;
for (int i = 2; i <= MAX; ++i)
{
if (!vis[i])
prime[cnt++] = i;
for (int j = 0; (j<cnt)&&(i*prime[j] <= MAX); ++j)
{
vis[i*prime[j]] = 1;
if(i%prime[j] == 0) break;
}
}
}
int flag[maxn],ans;
int save[maxn][2],pre,cache;
int main()
{
int n;
init_prim();
//cout<<cnt<<endl;
scanf("%d",&n);
memset(flag,0,sizeof(flag));
ans = 0;
int temp;
for(int i = 1;i<cnt;i++)
{
if(prime[i]>n/2)
break;
temp = 0;
int fac = 1;
while(fac*prime[i]<=n)
{
if(!flag[fac*prime[i]])
{
flag[fac*prime[i]] = 1;
temp++;
if(temp>2&&temp%2==0)
{
save[ans][0] = fac*prime[i];
save[ans][1] = cache;
ans++;
}
cache = fac*prime[i];
}
fac++;
}
if(temp%2==1){
flag[2*prime[i]] = 0;
temp--;
save[ans][0] = prime[i];
save[ans][1] = cache;
ans++;
}
else
{
save[ans][0] = prime[i];
save[ans][1] = 2*prime[i];
ans++;
}
}
temp = 0;
for(int i = 2;i<=n;i+=2)
{
if(!flag[i])
{
flag[i] = 1;
temp++;
if(temp%2==0)
{
save[ans][0] = i;
save[ans][1] = cache;
ans++;
}
cache = i;
}
}
cout<<ans<<endl;
for(int i = 0;i<ans;i++)
{
printf("%d %d\n",save[i][0],save[i][1]);
}
return 0;
}