VP AtCoder Beginner Contest 390
A - 12435
点击查看代码
void solve() {
int cnt = 0;
int a[6]{};
for (int i = 1; i <= 5; ++ i) {
std::cin >> a[i];
}
for (int i = 1; i <= 4; ++ i) {
cnt += (a[i] != i && a[i + 1] != i + 1);
}
if (cnt == 1) {
std::cout << "Yes\n";
} else {
std::cout << "No\n";
}
}
B - Geometric Sequence
题意:判断一个数列是不是等比数列。
如果用浮点数计算公比可能因为精度误差导致判断错误,可以分解为分数的形式,因为\(a_i : a_{i + 1} = a_1 : a_2, i \in [1, n]\),那么计算\(gcd\)搞个最简分数判断即可。
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
int x = a[0] / std::gcd(a[0], a[1]), y = a[1] / std::gcd(a[0], a[1]);
for (int i = 0; i + 1 < n; ++ i) {
int d = std::gcd(a[i], a[i + 1]);
if (a[i] / d != x || a[i + 1] / d != y) {
std::cout << "No\n";
return;
}
}
std::cout << "Yes\n";
}
C - Paint to make a rectangle
题意:有一个矩阵,有些地方涂了黑色,有些地方涂了白色,有些没有涂色。问能不能给所有格子涂色后使得所有黑色格子恰好成为一个矩阵。
找出已有的黑色格子的上下左右边界,判断里面有没有白色格子, 如果没有那么我们一定可以让这个子矩阵全是黑色,否则一个白色格子出现在这中间,不可能让黑色格子恰好形成一个矩阵。
点击查看代码
void solve() {
int n, m;
std::cin >> n >> m;
std::vector<std::string> s(n);
for (int i = 0; i < n; ++ i) {
std::cin >> s[i];
}
int a = n, b = 0, c = m, d = 0;
for (int i = 0; i < n; ++ i) {
for (int j = 0; j < m; ++ j) {
if (s[i][j] == '#') {
a = std::min(a, i);
b = std::max(b, i);
c = std::min(c, j);
d = std::max(d, j);
}
}
}
for (int i = 0; i < n; ++ i) {
for (int j = 0; j < m; ++ j) {
if (s[i][j] == '.' && i >= a && i <= b && j >= c && j <= d) {
std::cout << "No\n";
return;
}
}
}
std::cout << "Yes\n";
}
D - Stone XOR
题意:将\(n\)个数分成若干个集合,求所有情况下每个集合的和的异或和有多少种。
观察到\(n\)很小,可以爆搜。
每次讨论把\(a_i\)放到前面已有的集合还是自己单独分一个集合,复杂度大概是阶乘级别(应该吧)。
不过要吐槽一下卡set而不卡unordered_set。
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<i64> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
std::unordered_set<i64> s;
std::vector<i64> b;
auto dfs = [&](auto self, int u, i64 x) -> void {
if (u == n) {
s.insert(x);
return;
}
b.push_back(a[u]);
self(self, u + 1, x ^ a[u]);
b.pop_back();
for (auto & y : b) {
x ^= y;
y += a[u];
self(self, u + 1, x ^ y);
y -= a[u];
x ^= y;
}
};
dfs(dfs, 0, 0);
std::cout << s.size() << "\n";
}
E - Vitamin Balance
题意:有\(n\)个物品,所有物品总共分成三种。每个物品有价值和体积,你有\(m\)的容量,求在不超过容量的前提下三种物品的最小价值最大是多少。
分别对三类物品做01背包。然后枚举分给第一种物品多少容量和分给第二种物品多少容量,那么第三种物品的容量可以直接计算。然后取其中最小值的最大值即可。
点击查看代码
void solve() {
int n, m;
std::cin >> n >> m;
std::vector<std::pair<int, int> > a, b, c;
for (int i = 0; i < n; ++ i) {
int v, t, w;
std::cin >> t >> v >> w;
if (t == 1) {
a.push_back({w, v});
} else if (t == 2) {
b.push_back({w, v});
} else {
c.push_back({w, v});
}
}
auto dp = [&](std::vector<std::pair<int, int> > a) -> std::vector<int> {
std::vector<int> f(m + 1);
for (auto & [w, v] : a) {
for (int i = m; i >= w; -- i) {
f[i] = std::max(f[i], f[i - w] + v);
}
}
return f;
};
auto fa = dp(a), fb = dp(b), fc = dp(c);
int ans = 0;
for (int i = 1; i <= m; ++ i) {
for (int j = 1; i + j < m; ++ j) {
int k = m - i - j;
ans = std::max(ans, std::min({fa[i], fb[j], fc[k]}));
}
}
std::cout << ans << "\n";
}
F - Double Sum 3
待补

浙公网安备 33010602011771号