1. 程式人生 > 實用技巧 >2020牛客多校第三場H

2020牛客多校第三場H

題意:

在{1,2,3,...,n}中找到兩個沒有交集的序列使得gcd(ai, bi)>1,即找到ai和bi兩兩配對,使得他們不互質

思路:

顯而易見,> n/2的素數是不能配對的。我們可以先把1~n的素數篩出來,從大到小列舉每個素數p(從小到大會漏)。

對於每個素數p,2p,3p,...... ,kp (k == n / p)兩兩配對,如果k為奇數,則把2p留下。

最後把留下的偶數兩兩配對,得到最終答案。

Code:

#pragma GCC optimize(3)
#pragma GCC optimize(2)
#include <map>
#include <set
> #include <array> #include <queue> #include <stack> #include <cmath> #include <vector> #include <cstdio> #include <cstring> #include <sstream> #include <iostream> #include <stdlib.h> #include <algorithm> #include <unordered_map> using
namespace std; typedef long long ll; typedef pair<int, int> PII; #define Time (double)clock() / CLOCKS_PER_SEC #define sd(a) scanf("%d", &a) #define sdd(a, b) scanf("%d%d", &a, &b) #define slld(a) scanf("%lld", &a) #define slldd(a, b) scanf("%lld%lld", &a, &b) const
int N = 2e5 + 10; const ll M = 4e12; const int mod = 1e9 + 7; int t; int n, cnt; int primes[N]; bool st[N], vis[N]; vector<pair<int, int>> v; void get(int n) { cnt = 0; for (int i = 2; i <= n; i++) { if (!st[i]) primes[cnt++] = i; for (int j = 0; primes[j] <= n / i; j++) { st[primes[j] * i] = true; if (i % primes[j] == 0) break; } } } int main() { #ifdef ONLINE_JUDGE #else freopen("/home/jungu/code/in.txt", "r", stdin); // freopen("/home/jungu/code/out.txt", "w", stdout); #endif // ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); sd(t); get(N - 10); while (t--) { sd(n); for (int i = 1; i <= n; i++) { vis[i] = false; } v.clear(); int num = -1, a, b; for (int i = n / 2; i >= 2; i--) { if(st[i]) continue; if(i > n / 2) continue; int k = n / i * i; for( ; k >= 0; k -= i){ while(vis[k] && k >= 0){ k -= i; } if(k == 0){ break; } vis[k] = true; a = k; while(vis[k] && k >= 0){ k -= i; } if(k == 0){ break; } vis[k] = true; if(k == 2 * i){ if(num == -1){ num = k; } else{ v.push_back({k, num}); num = -1; } k -= i; vis[k] = true; } v.push_back({a, k}); } } printf("%d\n", (int)v.size()); for(auto x : v){ printf("%d %d\n", x.first, x.second); } } return 0; }