CF449C Jzzhu and Apples (筛素数 数论?

时间:2023-03-09 01:44:20
CF449C Jzzhu and Apples (筛素数 数论?

Codeforces Round #257 (Div. 1) C

Codeforces Round #257 (Div. 1) E

CF450E

C. Jzzhu and Apples
time limit per test

1 second

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 ≤ 105), 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.

Sample test(s)
Input
6
Output
2
6 3
2 4
Input
9
Output
3
9 3
2 4
6 8
Input
2
Output
0

题意:有N个苹果,编号为1~N。现要将苹果组成若干对,每对苹果最小公约数不为1。求最多能分成多少对,输出各对的组成。

题解:先筛素数,然后搞。

首先我们怕的是乱选了两个数组成了公约数不为1的一对,但是这导致了总对数减少(这两个数分别被别的数需要,它们组成一对了不是最优解)。为了防止这种情况,我们要想办法让总对数不会减少。

我们发现2的倍数们非常碉炸,任意2个就能组成1对,所以我们先弄其他的数,最后再搞2的倍数。

我们发现一个质数x的1倍、2倍、3倍、……?倍中未使用的数组成的集合,也可以任意两两组合,但是如果在1~n之间,这个集合的元素个数是奇数,就会多一个。为了不造成多余的影响,我们把2*x作为多出来的一个,扔到2的倍数中去。这样,各种集合的多出来的一个,肯定能找到配对。把我们使用的数标记一下,防止搞其他质数的时候重复用一个数。

先搞完3到小于等于(N/2)的质数(大于N/2,它的倍数的集合就只有它自己了,没法玩),然后搞2的倍数,把之前扔进来的2*x们和其他2*y(y是合数)组成一个大集合,两两配对,最后再多出来一个也没办法了,这已经是最多的配对了。

解不唯一,我们这样搞肯定能找到最多的对数,碉炸。

代码:

 //#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<stack>
#include<queue>
using namespace std;
#define ll long long
#define usll unsigned ll
#define mz(array) memset(array, 0, sizeof(array))
#define minf(array) memset(array, 0x3f, sizeof(array))
#define REP(i,n) for(i=0;i<(n);i++)
#define FOR(i,x,n) for(i=(x);i<=(n);i++)
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define WN(x) prllf("%d\n",x);
#define RE freopen("D.in","r",stdin)
#define WE freopen("1biao.out","w",stdout)
#define mp make_pair
#define pb push_back const long N = ;
int prime[N],pn = ;
bool isnp[N];
void shai() {
int i,j;
memset(prime,,sizeof(prime));
memset(isnp,,sizeof(isnp));
isnp[]=,isnp[]=;
pn=;
for(i = ; i < N ; i ++) {
if(! isnp[i])
prime[pn ++]=i;
//关键处1
for(j = ; j < pn && i * prime[j] < N ; j ++) {
isnp[i * prime[j]] = ;
if( !(i % prime[j] ) ) //关键处2
break;
}
}
} int n;
vector<int>a,a2;
vector<pair<int,int> >v;
bool used[N];
int main() {
int i,j,k;
int l,r,mid;
int pre;
int ans;
shai();
while(scanf("%d",&n)!=EOF) {
ans=;
v.clear();
a2.clear();
memset(used,,sizeof(used)); for(i=; prime[i]<=n/; i++) {
a.clear();
a.pb(prime[i]);
for(j=*prime[i]; j<=n; j+=prime[i]) if(!used[j]) a.pb(j);
if(a.size()%==) a2.pb(*prime[i]);
else a.pb(*prime[i]);
int maxj=a.size();
for(j=; j+<maxj; j+=) {
v.pb(mp(a[j],a[j+]));
used[a[j]]=;
used[a[j+]]=;
}
} if(n>=)a2.pb();
if(n>=)a2.pb();
for(i=; i+i<=n; i++) {
if(!used[i+i] && isnp[i]) a2.pb(i+i);
}
int maxi=a2.size();
for(i=; i+<maxi; i+=) v.pb(mp(a2[i],a2[i+]));
printf("%d\n",v.size());
maxi=v.size();
REP(i,maxi) printf("%d %d\n",v[i].first,v[i].second);
}
return ;
}