AtCoder Beginner Contest 165
比赛链接:https://atcoder.jp/contests/abc165/tasks
A - We Love Golf
题意
区间 $[a, b]$ 中是否存在 $k$ 的倍数。
代码
#include <bits/stdc++.h> using namespace std; int main() { int k, a, b; cin >> k >> a >> b; for (int i = a; i <= b; i++) { if (i % k == 0) { cout << "OK"; return 0; } } cout << "NG"; }
B - 1%
题意
一开始在银行存有 $100$ 元,年利率为 $\lfloor \frac{n}{100} \rfloor$,问多少年后存款不少于 $x$ 元。
代码
#include <bits/stdc++.h> using namespace std; int main() { long long x; cin >> x; long long sum = 100; for (int i = 1; i < INT_MAX; i++) { sum += sum / 100; if (sum >= x) { cout << i << "\n"; return 0; } } }
C - Many Requirements
题意
构造一个长为 $n$ 的数组 $A$,其中 $1 ≤ A_1 ≤ A_2 ≤ ... ≤ A_n ≤ m$。
另有数组 $a,b,c,d$,如果 $A_{b_i} - A_{a_i} = c_i$,则该数组的价值加上 $d_i$ ,求能构造出的数组的最大价值。
题解
枚举所有情况即可。
代码
#include <bits/stdc++.h> using namespace std; int n, m, q; int a[50], b[50], c[50], d[50]; int A[10], ans; void dfs(int dep, int pre) { if (dep == n) { int sum = 0; for (int i = 0; i < q; i++) if (A[b[i]] - A[a[i]] == c[i]) sum += d[i]; ans = max(ans, sum); return; } for (int i = pre; i <= m; i++) { A[dep] = i; dfs(dep + 1, i); } } int main() { cin >> n >> m >> q; for (int i = 0; i < q; i++) { cin >> a[i] >> b[i] >> c[i] >> d[i]; --a[i], --b[i]; } dfs(0, 1); cout << ans << "\n"; }
D - Floor Function
题意
求 $max( \lfloor \frac{Ax}{B} \rfloor - A \lfloor \frac{x}{B} \rfloor )$ 。
题解
设 $x = cB + d\ (0≤c,\ 0≤d<B)$
$\ \ \ \ \lfloor \frac{Ax}{B} \rfloor - A \lfloor \frac{x}{B} \rfloor$
$=\lfloor \frac{A(cB+d)}{B} \rfloor - A \lfloor \frac{cB+d}{B} \rfloor$
$=Ac + \lfloor \frac{Ad}{B} \rfloor - Ac - A \lfloor \frac{d}{B} \rfloor$
$=\lfloor \frac{Ad}{B} \rfloor - A \lfloor \frac{d}{B} \rfloor$
$=\lfloor \frac{Ad}{B} \rfloor$
即求 $max(\lfloor \frac{Ad}{B} \rfloor)$,取 $d$ 的最大值即可。
代码
#include <bits/stdc++.h> using namespace std; int main() { long long a, b, n; cin >> a >> b >> n; cout << a * min(b - 1, n) / b << "\n"; }
E - Rotation Matching
题意
有 $n$ 个选手,$m$ 个比赛场地,为每 $m$ 个比赛场地指定一对选手的编号(一个编号只能出现在一个比赛场地),来保证在之后的 $n$ 轮比赛中,所有选手不会与同一选手比赛两次,每轮比赛后所有选手编号加 $1$,编号 $n+1$ 的变为 $1$。
题解
一个选手最多的情况是要与 $m$ 个人一人比一次,所以 $m$ 对编号应取 $m$ 个不同的间隔。
即在 $[1, n]$ 中取 $m$ 对数,每对数间隔不同的长度。
代码
待填
F - LIS on Tree
题意
一棵有 $n$ 个结点的树,每个结点有一个值,输出每个从根节点 $1$ 到其他点最短路的值序列中 $LIS$ 的长度。
题解
维护一个最长单调序列即可。
代码一
#include <bits/stdc++.h> using namespace std; const int M = 2e5 + 100; vector<int> e[M]; int a[M], ans[M]; int b[M], len; void dfs(int u, int pre) { int id = lower_bound(b, b + len, a[u]) - b; int del = -1; if (id == len) ++len; else del = b[id]; b[id] = a[u]; ans[u] = len; for (auto v : e[u]) { if (v != pre) { dfs(v, u); } } if (del == -1) --len; else b[id] = del; } int main() { int n; cin >> n; for (int i = 0; i < n; i++) cin >> a[i]; for (int i = 0; i < n - 1; i++) { int u, v; cin >> u >> v; --u, --v; e[u].push_back(v); e[v].push_back(u); } dfs(0, -1); for (int i = 0; i < n; i++) cout << ans[i] << "\n"; }
代码二
再贴一下用 $set$ 的做法,需要注意一些语句的前后顺序。
#include <bits/stdc++.h> using namespace std; const int M = 2e5 + 100; vector<int> e[M]; int a[M], ans[M]; set<int> st; void dfs(int u, int pre) { auto it = st.lower_bound(a[u]); int del = -1; if (it != st.end()) { del = *it; st.erase(it); } st.insert(a[u]); ans[u] = st.size(); for (auto v : e[u]) { if (v != pre) { dfs(v, u); } } st.erase(a[u]); if (del != -1) st.insert(del); } int main() { int n; cin >> n; for (int i = 0; i < n; i++) cin >> a[i]; for (int i = 0; i < n - 1; i++) { int u, v; cin >> u >> v; --u, --v; e[u].push_back(v); e[v].push_back(u); } dfs(0, -1); for (int i = 0; i < n; i++) cout << ans[i] << "\n"; }