这道题正解是怎么对的其实我也不清楚,总之靠感性理解吧。
首先当然要把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 }