牛客多校第四場自閉
阿新 • • 發佈:2020-07-23
自閉場,不想多說,能做的就2個簽到和H了,難度2.0就是字典樹上字尾自動機,知識儲備限制了我的想象
H-Harder Gcd Problem
先掛個線性篩把範圍內素數都篩一下,然後直接lowerbound找到第一個小於n的素數位置(實際上至少要小於等於n/2,我懶,直接lowerbound到n了),然後從大往小依次處理
對於每一個素數,讓\(j=(n/p[i])*p[i]\)(即找到最後一個j使得jp[i]<=n),然後把j向1列舉,每兩個jp[i]組成一對答案,但對於j為奇數的情況,2*p[i]得先暫時保留
最後再遍歷沒被匹配的數,這時剛剛2*p[i]中帶有2的因子,因此他們也能夠相互匹配,這樣再把它們兩兩匹配
我的處理是先讓1*p[i]處於待匹配狀態,若j為偶數,則2也能被匹配;若j為奇數,則2只能進入待匹配狀態,而不會被匹配
#pragma GCC optimize(2) #include<bits/stdc++.h> #define ll long long #define fastio ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL); using namespace std; double pi = acos(-1); const double eps = 1e-12; const int maxn = 4e5 + 10; const int inf = 1e9; ll mod = 1e9 + 7; int read() { int x = 0, f = 1; char c = getchar(); while (c < '0' || c>'9') { if (c == '-') f = -1; c = getchar(); } while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + c - '0', c = getchar(); return f * x; } int v[maxn], p[maxn], ecnt, vis[maxn], cnt = 0; void Euler_sieve(int n) { ecnt = 0; for (int i = 2; i <= n; i++) { if (v[i] == 0) { v[i] = i; p[++ecnt] = i; } for (int j = 1; j <= ecnt; j++) { if (p[j] > v[i] || p[j] > n / i)break; v[i * p[j]] = p[j]; } } } struct an { int a, b; }ans[maxn]; int main() { fastio; int t; cin >> t; Euler_sieve(3e5 + 5); while(t--) { memset(vis, 0, sizeof(vis)); int n; cin >> n; cnt = 0; int P = lower_bound(p + 1, p + 1 + ecnt, n) - p - 1; int tmp = -1; for (int i = P; i >= 1; i--) { tmp = p[i]; for (int j = n / p[i] * p[i]; j > p[i]; j -= p[i]) { if (!vis[j]) { if (tmp == -1) tmp = j; else { ans[++cnt] = { tmp,j }; vis[tmp] = vis[j] = 1; tmp = -1; } } } } tmp = -1; for (int i = 2; i <= n; i += 2) { if (!vis[i]) if (tmp == -1) tmp = i; else { ans[++cnt] = { tmp,i }; vis[tmp] = vis[i] = 1; tmp = -1; } } cout << cnt << endl; for (int i = 1; i <= cnt; i++) cout << ans[i].a << " " << ans[i].b << endl; } return 0; }