题目链接:http://codeforces.com/problemset/problem/449/C
给你n个数,从1到n。然后从这些数中挑选出不互质的数对最多有多少对。
先是素数筛,显然2的倍数的个数是最多的,所以最后处理。然后处理3,5,7,11...的倍数的数,之前已经挑过的就不能再选了。要是一个素数p的倍数个数是奇数,就把2*p给2
的倍数。这样可以满足p倍数搭配的对数是最优的。最后处理2的倍数就行了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 1e5 + 5; 4 bool prime[N] , vis[N]; 5 int p[N / 3]; 6 vector <int> G[N]; 7 8 void init() { 9 int index = 0; 10 prime[1] = true; 11 for(int i = 2 ; i < N ; ++i) { 12 if(!prime[i]) { 13 p[++index] = i; 14 for(int j = i * 2 ; j < N ; j += i) 15 prime[j] = true; 16 } 17 } 18 } 19 20 int main() 21 { 22 init(); 23 int n; 24 scanf("%d" , &n); 25 if(n < 4) { 26 printf("0 "); 27 return 0; 28 } 29 int cnt = 0; 30 for(int i = 2 ; p[i] * 2 <= n ; ++i) { 31 for(int j = p[i] ; j <= n ; j += p[i]) { 32 if(!vis[j]) { 33 vis[j] = true; 34 G[p[i]].push_back(j); 35 } 36 } 37 if(G[p[i]].size() >= 3 && (G[p[i]].size() % 2)) 38 G[2].push_back(p[i] * 2); 39 cnt += G[p[i]].size() / 2; 40 } 41 for(int i = 2 ; i <= n ; i += 2) { 42 if(!vis[i]) 43 G[2].push_back(i); 44 } 45 cnt += G[2].size() / 2; 46 printf("%d " , cnt); 47 for(int i = 1 ; i < G[2].size() ; i += 2) 48 printf("%d %d " , G[2][i - 1] , G[2][i]); 49 for(int i = 2 ; p[i] * 2 <= n ; ++i) { 50 if(G[p[i]].size() % 2) { 51 printf("%d %d " , G[p[i]][0] , G[p[i]][2]); 52 for(int j = 4 ; j < G[p[i]].size() ; j += 2) 53 printf("%d %d " , G[p[i]][j - 1] , G[p[i]][j]); 54 } 55 else { 56 for(int j = 1 ; j < G[p[i]].size() ; j += 2) 57 printf("%d %d " , G[p[i]][j - 1] , G[p[i]][j]); 58 } 59 } 60 return 0; 61 }