【CodeForces】CodeForces Round #511 (Div. 1) 題解
阿新 • • 發佈:2018-11-08
【比賽連結】
【題解連結】
**【A】**Enlarge GCD
【思路要點】
- 令所有數的 為 ,將所有數除去 ,問題變為了所有數的 為 的情況。
- 我們要選出一個最大的數集,使得這個數集中的數存在不為 的公因數。
- 顯然我們只需要考慮所有質數即可,線性篩求出每個數的最小質因子,質因數分解每一個數即可。
- 時間複雜度 。
【程式碼】
#include<bits/stdc++.h> using namespace std; const int MAXN = 3e5 + 5; const int MAXV = 1.5e7 + 5; typedef long long ll; typedef long double ld; typedef unsigned long long ull; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } int n, tot, a[MAXN], prime[MAXV], f[MAXV], cnt[MAXV]; void init(int n) { for (int i = 2; i <= n; i++) { if (f[i] == 0) prime[++tot] = f[i] = i; for (int j = 1; j <= tot && prime[j] <= f[i]; j++) { int tmp = prime[j] * i; if (tmp > n) break; f[tmp] = prime[j]; } } } int gcd(int x, int y) { if (y == 0) return x; else return gcd(y, x % y); } int main() { init(1.5e7); int g = 0; read(n); for (int i = 1; i <= n; i++) { read(a[i]); g = gcd(a[i], g); } int ans = 0; for (int i = 1; i <= n; i++) { int tmp = a[i] / g; while (tmp != 1) { cnt[f[tmp]]++; if (cnt[f[tmp]] > ans) ans = cnt[f[tmp]]; int tnp = f[tmp]; while (tmp % tnp == 0) tmp /= tnp; } } if (ans == 0) printf("-1\n"); else printf("%d\n", n - ans); return 0; }
**【B】**Little C Loves 3 II
【思路要點】
打表題。- 不妨令 。
- 用最大流求出 較小的時候的答案,我們發現當 足夠大時,答案為 ,特殊處理 的情況即可。
或者你也可以直接交一張表。- 時間複雜度 。
【程式碼】
#include<bits/stdc++.h> using namespace std; const int MAXN = 2e5 + 5; typedef long long ll; typedef long double ld; typedef unsigned long long ull; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } int main() { ll n, m; read(n), read(m); if (n > m) swap(n, m); if (n == 1) { ll ans = m / 6 * 6; ll tmp = m % 6; ans += max(0ll, tmp - 3) * 2; writeln(ans); } else if (n == 2) { ll ans = n * m; if (m == 2) ans -= 4; if (m == 3) ans -= 2; if (m == 7) ans -= 2; writeln(ans); } else writeln(n * m - n * m % 2); return 0; }
**【C】**Region Separation
【思路要點】
- 令 號節點為根,節點 的子樹權值和為 。
- 若給定 ,一棵樹能夠被分成權值和相同的 部分的充要條件為 為整數,並且存在 個子樹 滿足 是 的整數倍。
- 因此,我們可以先計算出對於每一個 ,滿足 是 的整數倍的子樹 的個數 ,然後,在合法的 上簡單 ,得到答案。
- 考慮一個子樹 對 的貢獻,由於