AtCoder Beginner Contest 060
A
一行给三个字符串 \(A, B, C\) ,询问是否 \(A\) 的最后一个字符对于 \(B\) 的第一个字符,\(B\) 的最后一个字符等于 \(C\) 的第一个字符。
std::string s; std::getline(std::cin, s);
char last = ' ';
int ok = 1;
for (int i = 0; i < s.size(); i++) {
if (i + 1 < s.size() && s[i + 1] == ' ')
last = s[i];
if (i - 1 >= 0 && s[i - 1] == ' ')
ok &= s[i] == last;
}
std::cout << (ok ? "YES" : "NO") << "\n";
B
题意:
给定正整数 \(A\) ,你可以选择任意个数,但至少是一个且都是 \(A\) 的倍数。
给定正整数 \(B\) ,整数 \(C\) 。询问是否可以选择若干个数,使它们的和满足 \(\bmod B = C\) 。
\(1 \leq A, B \leq 100, 0 \leq C < B\)
题解:
若干个 \(A\) 的倍数之和依旧是 \(A\) 的倍数,这是在询问是否存在 \(A\) 的倍数满足 \(pA \bmod B = C\) 。
即是否存在 \(xA + yB = C\) 。由裴蜀定理只需 \(gcd(A, B) \mid C\) 。
ll A, B, C; std::cin >> A >> B >> C;
std::cout << (C % gcd(A, B) == 0 ? "YES" : "NO") << "\n";
时间复杂度 \(O(\log A)\) 。
C
题意:
一个喷头,如果按下开关会喷水 \(T\) 秒。如果在第 \(i\) 秒按下水龙头,喷头会喷水到 \(i + T - 1\) 秒。
有 \(N\) 个人经过喷头,第 \(i\) 个人经过的时间是 \(t_i\) ,且经过时会按下喷头开关。
询问喷头总共喷水多少秒。
\(1 \leq N \leq 2 \times 10^{5}, 1 \leq T \leq 10^{9}\)
\(0 \leq t_1 < t_2 < t_3 \cdots < t_{N - 1} < t_{N} \leq 10^{9}\)
题解:
记上次喷水结束的时间 \(end\) 。
\(ans += min(T, max(t_i + T - 1 - end, 0))\) ,则 \(end = t_i + T - 1\) 。
int N, T; std::cin >> N >> T;
ll ans = 0, end = -1;
for (int i = 1; i <= N; i++) {
int t; std::cin >> t;
if (end == -1) ans += T, end = t + T - 1;
else ans += std::min(1LL * T, std::max(0LL, 1LL * t + T - 1 - end));
end = t + T - 1;
}
std::cout << ans << "\n";
D
题意:
你有 \(N\) 个物品和一个容量为 \(W\) 的背包。第 \(i\) 种物品的重量为 \(w_i\) 价值为 \(v_i\) 。
你可以选择一些物品放入背包,并且让背包内物品的价值最大。询问最大价值。
\(1 \leq N \leq 100, 1 \leq W \leq 10^{9}\)
\(1 \leq w_i \leq 10^{9}, 1 \leq v_i \leq 10^{7}\)
\(\forall i \in [2, N], w_1 \leq w_i \leq w_1 + 3\)
题解:
官方题解说这是个广为人知的 01 背包。
但是 01 背包的正常解是 \(O(NW)\) 的,这里只 \(W\) 也已经超过 \(10^{8}\) 了。
抄一抄官方解。
注意到限制:\(w_1 \leq w_i \leq w_1 + 3\) 。这意味着最多 \(4\) 种物品重量。
对每个 \(w\) ,固定一个 \(k_w\) :被选择的重量为 \(w\) 的物品数量。
\(k_w\) 可以被枚举。显然的,对价值排序后,贪心地选 \(k_w\) 。
让 \(A = w_1, B = w_1 + 1, C = w_1 + 2, D = w_1 + 3\) 。
每个数量枚举是 \(O(N)\) 的,每次计算是 \(O(N)\) 的。
可以枚举出前三个 \(A, B, C\) 。计算出 \(rem\) ,\(D = \lfloor \frac{rem}{w1 + 3} \rfloor\) 。
时间复杂度为 \(O(ABCD) = T((\frac{N}{4})^{4}) = T(\frac{N^{4}}{256})\) 。
int N, W; std::cin >> N >> W;
std::vector<std::vector<int> > a(4, std::vector<int>());
int w1 = 0;
for (int i = 1; i <= N; i++) {
int w, v; std::cin >> w >> v;
if (i == 1) w1 = w;
a[w - w1].push_back(v);
}
for (int i = 0; i < 4; i++) {
std::sort(a[i].begin(), a[i].end(), std::greater<int>());
}
ll ans = 0;
for (int A = 0; A <= (int)a[0].size(); A++) {
for (int B = 0; B <= (int)a[1].size(); B++) {
for (int C = 0; C <= (int)a[2].size(); C++) {
ll sum = 0, val = 0;
int ok = 1;
for (int i = 1; i <= A && ok; i++) sum += w1 + 0, val += a[0][i - 1], ok &= sum <= W;
for (int i = 1; i <= B && ok; i++) sum += w1 + 1, val += a[1][i - 1], ok &= sum <= W;
for (int i = 1; i <= C && ok; i++) sum += w1 + 2, val += a[2][i - 1], ok &= sum <= W;
if (ok) {
int rem = W - sum;
int D = std::min(rem / (w1 + 3), (int)a[3].size());
for (int i = 1; i <= D && ok; i++) sum += w1 + 3, val += a[3][i - 1], ok &= sum <= W;
}
if (ok)
ans = std::max(val, ans);
}
}
}
std::cout << ans << "\n";
浙公网安备 33010602011771号