AtCoder Beginner Contest 178
比賽連結:https://atcoder.jp/contests/abc178/tasks
A - not
題意
給出一個整數 $0 \le x \le 1$,如果 $x$ 是 $0$ 就輸出 $1$,如果 $x$ 是 $1$ 就輸出 $0$ 。
題解
輸出 $x \oplus 1$ 或 $!x$ 均可。
程式碼
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int x; cin >> x; cout<< (x ^ 1)<< "\n"; return 0; }
B - Product Max
題意
給出 $a,b,c,d$,問 $x \times y$ 的最大值。($-10^9 \leq a \leq x \leq b \leq 10^9$,$-10^9 \leq c \leq y \leq d \leq 10^9$)
題解
相似題目:CF1406B,列舉四個端點之積即可。
簡單解釋一下:
- 當 $x,y$ 均為正數或正端點之積較大,此時答案為 $b \times d$
- 當 $x,y$ 均為負數或負端點之積較大,此時答案為 $a \times c$
- 當 $x,y$ 一方為正數一方為負數,此時答案為 $a \times d$ 或 $b \times c$
程式碼
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); long long a, b, c, d; cin >> a >> b >> c >> d; cout << max({a * c, a * d, b * c, b * d}) << "\n"; return 0; }
C - Ubiquity
題意
找出滿足以下條件的長為 $n$ 的不同序列的個數:
- $0 \le a_i \le 9$
- 序列中至少有一個 $a_i = 0$
- 序列中至少有一個$a_i = 9$
答案對 $10^9+7$ 取模。
題解
總的序列個數為 $10^n$,
不含 $0$ 的序列個數為 $9^n$,
不含 $9$ 的序列個數為 $9^n$,
不含 $0$ 和 $9$ 的序列個數為 $8^n$,
根據容斥原理,答案即 $10^n - 2 \times 9^n + 8 ^ n$ 。
程式碼
#include <bits/stdc++.h> using namespace std; const int MOD = 1e9 + 7; int binpow(int a, int b) { int res = 1; while (b) { if (b & 1) res = 1LL * res * a % MOD; a = 1LL * a * a % MOD; b >>= 1; } return res; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; cout << (0LL + binpow(10, n) - 2 * binpow(9, n) + binpow(8, n) + 2 * MOD) % MOD << "\n"; return 0; }
D - Redistribution
題意
給出一個正整數 $s$,問有多少序列滿足 $a_i \ge 3$,且序列和為 $s$,答案對 $10^9+7$ 取模。
題解一
設 $dp_i$ 為序列和為 $i$ 的序列個數。
初始時只有序列為空這一種情況,即 $dp_0 = 1$,之後每次向序列中新增大於等於 $3$ 的元素,最終答案即 $dp_s$ 。
程式碼
#include <bits/stdc++.h> using namespace std; constexpr int MOD = 1e9 + 7; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int s; cin >> s; vector<int> dp(2020); dp[0] = 1; for (int i = 0; i <= s; i++) { for (int j = 3; i + j <= s; j++) { (dp[i + j] += dp[i]) %= MOD; } } cout << dp[s] << "\n"; return 0; }
題解二
已知序列和為 $s$ ,列舉序列的長度 $i$ 。
因為每個元素都大於等於 $3$,假設每個元素都為 $3$ ,可以將多出來的 $ s-3*i$ 個 $1$,看作 $n$ 個相同的小球放入 $m=i$ 個可為空的相同的盒子中。
此時即轉化為組合數學十二路問題中的 $ULA$ 問題,答案即 $\sum_{i = 1}^{\lfloor \frac{s}{3} \rfloor}C_{n+m - 1}^{m - 1}$ 。
程式碼
#include <bits/stdc++.h> using namespace std; constexpr int N = 1e6 + 100; constexpr int MOD = 1e9 + 7; int fac[N], inv[N]; int binpow(int a, int b) { int res = 1; while (b) { if (b & 1) res = 1LL * res * a % MOD; a = 1LL * a * a % MOD; b >>= 1; } return res; } int C(int n, int m){ if(m < 0 or m > n) return 0; return 1LL * fac[n] * inv[m] % MOD * inv[n - m] % MOD; } void Init(){ fac[0] = 1; for (int i = 1; i < N; i++) fac[i] = 1LL * fac[i - 1] * i % MOD; inv[N - 1] = binpow(fac[N - 1], MOD - 2); for (int i = N - 2; i >= 0; i--) inv[i] = 1LL * inv[i + 1] * (i + 1) % MOD; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); Init(); int s; cin >> s; long long ans = 0; for (int i = 1; i <= s / 3; i++) { (ans += C(s - 3 * i + i - 1, i - 1)) %= MOD; } cout << ans << "\n"; return 0; }
E - Dist Max
題意
在二維平面中給出 $n$ 個點,問兩點間的最遠曼哈頓距離。
題解
$(x_i,y_i), (x_j, y_j)$ 間的曼哈頓距離為 $|x_i-x_j| + |y_i-y_j|$ 。
假設 $x_i \ge x_j$,那麼兩點間的距離可能有兩種情況:
- $(x_i-x_j) + (y_i-y_j)$,移項得:$(x_i+y_i) - (x_j+ y_j)$
- $(x_i-x_j) + (y_j-y_i)$,移項得:$(x_i-y_i) - (x_j- y_j)$
所以對於每個點的座標 $(x,y)$,分別用兩個陣列儲存 $x+y$ 和 $x-y$,然後取兩個陣列較大的最值差即可。
程式碼
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector<int> a(n), b(n); for (int i = 0; i < n; i++) { int x, y; cin >> x >> y; a[i] = x + y; b[i] = x - y; } sort(a.begin(), a.end()); sort(b.begin(), b.end()); cout << max(a.back() - a.front(), b.back() - b.front()) << "\n"; return 0; }
F - Contrast
題意
給出兩個非遞減序列 $a$ 和 $b$,問能否重排 $b$ 使得 $a_i \ne b_i $ 。
題解
待填。