AtCoder Beginner Contest 208 A~E個人題解
阿新 • • 發佈:2021-07-05
比賽連結:Here
A - Rolling Dice
水題
一個六面的骰子,請問搖動 \(A\) 次最後的點數和能否為 \(B\)
如果 \(B \in [a,6a]\) 輸出 YES
- C++
void solve() {
int a, b; cin >> a >> b;
if (a * 1 <= b && a * 6 >= b)cout << "Yes\n"; else cout << "No\n";
}
- Python
A,B = map(int,input().split()) if A <= B <= 6 * A: print("Yes") else: print("No")
B - Factorial Yen Coin
找零問題 or 完全揹包問題
- C++
void solve() {
ll n;
cin >> n;
int i = 2, cnt = 0;
while (n) {
cnt += n % i;
n /= i++;
}
cout << cnt << "\n";
}
另一種寫法
int fac(int i) {return i ? fac(i - 1) * i : 1;} void solve() { int n; cin >> n; int cnt = 0; for (int i = 1; i <= 10; ++i) { int div = fac(i + 1); int res = n % div; cnt += res / fac(i); n -= res; } cout << cnt << "\n"; }
- Python
from math import factorial
P = int(input())
answer = 0
for i in range(10, 0, -1):
while factorial(i) <= P:
answer += 1
P -= factorial(i)
print(answer)
C - Fair Candy Distribution
構造
一開始想錯了,想模擬寫。但在寫樣例時發現這個是對 k 平均分配,對於排序之後 \(k \%\ n\) 小的需要 + 1
- C++
void solve() { int n; ll k; cin >> n >> k; vector<ll>a(n), b(n); for (int i = 0; i < n; ++i) cin >> a[i], b[i] = a[i]; sort(a.begin(), a.end()); for (int i = 0; i < n; ++i) { if (b[i] < a[k % n])cout << k / n + 1 << "\n"; else cout << k / n << "\n"; } }
- Python
n, k = map(int, input().split())
A = list(map(int, input().split()))
B = sorted(A)
print(*[k // n + (A[i] < B[k % n]) for i in range(n)])
D - Shortest Path Queries 2
最短路問題
跑 FLoyd 最短路即可
- C++
const int N = 410, mod = 1e9 + 7;
ll f[N][N];
void solve() {
memset(f, 0x3f, sizeof(f));
ll n, m; cin >> n >> m;
for (int i = 1; i <= n; ++i)f[i][i] = 0;
for (int i = 0, a, b, c; i < m; ++i) {
cin >> a >> b >> c;
f[a][b] = c;
}
ll cnt = 0;
for (int k = 1; k <= n; ++k)
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
cnt += ((f[i][j] = min(f[i][j], f[i][k] + f[k][j])) != f[0][0]) ? f[i][j] : 0;
cout << cnt << "\n";
}
- Python (TLE)
import sys
n, m = map(int, sys.stdin.buffer.readline().split())
ABC = map(int, sys.stdin.buffer.read().split())
d = [[1 << 60] * n for i in range(n)]
for i in range(n):
d[i][i] = 0
for a, b, c in zip(ABC, ABC, ABC):
d[a - 1][b - 1] = c
cnt = 0
for k in range(n):
nxt = [[0] * n for i in range(n)]
for i in range(n):
for j in range(n):
nxt[i][j] = min(d[i][j], d[i][k] + d[k][j])
if nxt[i][j] < (1 << 59):
cnt += nxt[i][j]
d = nxt
print(cnt)
E - Digit Products
數位 DP ,時間複雜度:\(\mathcal{O}(log\ n)\)
對於這道題來說,如果一個個去構造肯定是是 TLE (\(n < 1e18\)),所以我們利用數位 DP (一種著名的組合演算法,用於快速計算受數字約束的、不超過 \(n\) 的整數)
- 構造一個 DP狀態:即到目前為止確定的前 i 個數字是否嚴格小於 \(n\) 個數字
- 狀態轉移方程:\(dp_{i,p}:=\) 前 \(i\) 位(\(0\)除外)的組合數,其乘積為\(p\)
- 同樣,設 \(eq_i :=\)(N的前 \(i\) 位的乘積)。
using ll = long long;
unordered_map<ll, ll>f[23];
ll n, k;
vector<int>a;
ll fun(ll x, ll y, ll z, ll t) {
if (!x)return y <= k;
if (!z and !t and f[x][y])return f[x][y];
ll ans = 0;
for (ll i = 0; i <= (z ? a[x - 1] : 9); ++i)
ans += fun(x - 1, y * (!i and t ? 1 : i), z and i == a[x - 1], t and !i);
if (!z and !t)f[x][y] = ans;
return ans;
}
void solve() {
cin >> n >> k;
while (n)a.push_back(n % 10), n /= 10;
cout << fun(a.size(), 1, 1, 1) - 1;
}
The desire of his soul is the prophecy of his fate
你靈魂的慾望,是你命運的先知。