CF449C Jzzhu and Apples

嘟嘟嘟

 

这道题正解是怎么对的其实我也不清楚,总之靠感性理解吧。

首先当然要把1到n / 2的素数都筛出来,因为两两能配对的数一定都是这些素数的倍数。这也就说明对于(n / 2, n]的素数,他们一定不能配对,所以就不用筛他们了。

筛完后我们考虑怎么配对,对于一个素数的所有倍数xi,他们任意两个都可以配对,但是可能配对完后得到的总配对数会减少。因此我们从最大的素数开始两两配对,感性理解就是越大的素数的倍数就越少,因此先尽量满足配对方案少的素数,然后再处理配对方案多的素数。

还有一点,就是当xi的倍数中没有配对的数是奇数个的时候,就会多出来一个,那么我们应该把哪一个丢出来呢?还是按照上面贪心的方法想:丢出来的数成功配对的可能性越大越好,即他的最小质因子越小越好。那么就应该丢掉2 * xi

讲 完 了

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<cctype>
 8 #include<vector>
 9 #include<stack>
10 #include<queue>
11 using namespace std;
12 #define enter puts("") 
13 #define space putchar(' ')
14 #define Mem(a, x) memset(a, x, sizeof(a))
15 #define rg register
16 typedef long long ll;
17 typedef double db;
18 const int INF = 0x3f3f3f3f;
19 const db eps = 1e-8;
20 const int maxn = 1e5 + 5;
21 inline ll read()
22 {
23     ll ans = 0;
24     char ch = getchar(), last = ' ';
25     while(!isdigit(ch)) {last = ch; ch = getchar();}
26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
27     if(last == '-') ans = -ans;
28     return ans;
29 }
30 inline void write(ll x)
31 {
32     if(x < 0) x = -x, putchar('-');
33     if(x >= 10) write(x / 10);
34     putchar(x % 10 + '0');
35 }
36 
37 bool vis[maxn];
38 struct Node
39 {
40   int x, y;
41 }ans[maxn];
42 int n, cnt = 0;
43 
44 int prime[maxn], v[maxn];
45 void init(int n)
46 {
47   for(int i = 2; i <= n; ++i)
48     {
49       if(!v[i]) v[i] = i, prime[++prime[0]] = i;
50       for(int j = 1; i * prime[j] <= n && j <= prime[0]; ++j)
51     {
52       if(prime[j] > v[i]) break;
53       v[i * prime[j]] = prime[j];
54     }
55     }
56 }
57 
58 
59 int main()
60 {
61   n = read();
62   init(n >> 1);
63   for(int i = prime[0]; i; --i)
64     {
65       int flg = 0; int las = 0;
66       for(int j = prime[i]; j <= n; j += prime[i]) if(!vis[j]) flg ^= 1;  //记录奇偶
67       for(int j = prime[i]; j <= n; j += prime[i])
68     {
69       if(j == (prime[i] << 1) && flg && prime[i] != 2) continue;
70       if(las && !vis[j])
71         {
72           vis[j] = 1;
73           ans[++cnt] = (Node){las, j};
74           las = 0;
75         }
76       else if(!las && !vis[j]) las = j, vis[j] = 1;
77     }
78     }
79   write(cnt); enter;
80   for(int i = 1; i <= cnt; ++i) write(ans[i].x), space, write(ans[i].y), enter;
81   return 0;
82 }
View Code

 

posted @ 2018-10-12 13:00  mrclr  阅读(145)  评论(0编辑  收藏  举报