TOYOTA SYSTEMS Programming Contest 2025(AtCoder Beginner Contest 431)
A - Robot Balance
点击查看代码
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int a, b;
std::cin >> a >> b;
std::cout << std::max(0, a - b) << "\n";
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
int t = 1;
// std::cin >> t;
while (t -- ) {
solve();
}
return 0;
}
B - Robot Weight
点击查看代码
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int x, n;
std::cin >> x >> n;
std::vector<int> a(n), st(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
int q;
std::cin >> q;
while (q -- ) {
int id;
std::cin >> id;
-- id;
if (st[id]) {
x -= a[id];
} else {
x += a[id];
}
st[id] ^= 1;
std::cout << x << "\n";
}
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
int t = 1;
// std::cin >> t;
while (t -- ) {
solve();
}
return 0;
}
C - Robot Factory
题意:两个数组\(a, b\)。如果\(a_i \leq b_j\)则可以匹配这两个元素。求最多匹配多少对。
两个数组从小到大排序,双指针找一下每个大于等于\(a_i\)的\(b_j\)。
点击查看代码
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int n, m, k;
std::cin >> n >> m >> k;
std::vector<int> a(n), b(m);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
for (int i = 0; i < m; ++ i) {
std::cin >> b[i];
}
std::ranges::sort(a);
std::ranges::sort(b);
for (int i = 0, j = 0; i < n && j < m; ++ i) {
while (j < m && b[j] < a[i]) {
++ j;
}
if (j < m) {
-- k;
++ j;
} else {
break;
}
}
if (k <= 0) {
std::cout << "Yes\n";
} else {
std::cout << "No\n";
}
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
int t = 1;
// std::cin >> t;
while (t -- ) {
solve();
}
return 0;
}
D - Robot Customize
题意:\(n\)个零件,每个零件重量为\(w_i\)。如果这个零件加入头部获得\(h_i\)价值,否则加入身体获得\(b_i\)价值。求一种分配方案,满足头部总重量小于等于身体总重量,且总价值最大。\(n \leq 500, w_i \leq 500\)。
记\(f_{i, j}\)表示前\(i\)个零件身体占\(j\)重量的最大花费。那么枚举这个零件作为头部还是身体进行转移即可。
如果\(\sum_{i=1}^{n} w_i - j \leq j\),则\(ans = \max(ans, f_{n, j})\)。
点击查看代码
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int n;
std::cin >> n;
std::vector<int> w(n), h(n), b(n);
for (int i = 0; i < n; ++ i) {
std::cin >> w[i] >> h[i] >> b[i];
}
int m = std::accumulate(w.begin(), w.end(), 0);
std::vector<i64> f(m + 1);
int pre = 0;
for (int i = 0; i < n; ++ i) {
std::vector<i64> g(m + 1);
for (int j = 0; j <= pre; ++ j) {
g[j + w[i]] = std::max(g[j + w[i]], f[j] + b[i]);
g[j] = std::max(g[j], f[j] + h[i]);
}
f = g;
pre += w[i];
}
i64 ans = 0;
for (int i = (m + 1) / 2; i <= m; ++ i) {
ans = std::max(ans, f[i]);
}
std::cout << ans << "\n";
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
int t = 1;
// std::cin >> t;
while (t -- ) {
solve();
}
return 0;
}
E - Reflection on Grid
题意:一个\(n\times m\)的矩阵,有两种镜子,每个位置要么是一种镜子要么没镜子。从\((1, 1)\)的左边射进来一束光,你想让其从\((n, m)\)的右边射出。你可以修改一些位置,求最小修改数量。
记\(dist[i][j][k]\)表示位置\((i, j)\)射进来一道往\(k\)方向的光的最小修改数。其中\(k \in [0, 3]\)分别代表上右下左四个方向。那么可以讨论是否修改,不同状态会射到不同的格子,\(01bfs\)跑一下即可。
点击查看代码
#include <bits/stdc++.h>
using i64 = long long;
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];
}
constexpr int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
auto get = [&](int x, int y, char c, int d) -> std::tuple<int, int, int> {
if (c == 'A') {
return {x + dx[d], y + dy[d], d};
}
if (c == 'B') {
if (d == 0) {
return {x, y - 1, 3};
} else if (d == 1) {
return {x + 1, y, 2};
} else if (d == 2) {
return {x, y + 1, 1};
} else {
return {x - 1, y, 0};
}
} else {
if (d == 0) {
return {x, y + 1, 1};
} else if (d == 1) {
return {x - 1, y, 0};
} else if (d == 2) {
return {x, y - 1, 3};
} else {
return {x + 1, y, 2};
}
}
};
constexpr int inf = 1e9;
std::vector dist(n, std::vector(m, std::array<int, 4>{inf, inf, inf, inf}));
dist[0][0][1] = 0;
std::deque<std::tuple<int, int, int>> q;
q.emplace_back(0, 0, 1);
while (q.size()) {
auto [x, y, d] = q.front(); q.pop_front();
for (char c = 'A'; c <= 'C'; ++ c) {
auto [nx, ny, nd] = get(x, y, c, d);
int w = c != s[x][y];
if (nx < 0 || nx >= n || ny < 0 || ny >= m || dist[nx][ny][nd] <= dist[x][y][d] + w) {
continue;
}
dist[nx][ny][nd] = dist[x][y][d] + w;
if (w) {
q.emplace_back(nx, ny, nd);
} else {
q.emplace_front(nx, ny, nd);
}
}
}
int ans = inf;
for (int i = 0; i < 4; ++ i) {
for (char c = 'A'; c <= 'C'; ++ c) {
auto [x, y, d] = get(n - 1, m - 1, c, i);
if (x == n - 1 && y == m) {
ans = std::min(ans, dist[n - 1][m - 1][i] + (c != s[n - 1][m - 1]));
}
}
}
std::cout << ans << "\n";
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
int t = 1;
std::cin >> t;
while (t -- ) {
solve();
}
return 0;
}
F - Almost Sorted 2
题意:一个长度为\(n\)的数组\(a\),你要将其重排,求可以得到多少个不同的数组\(b\),满足\(b_{i+1} \geq b_i - d\)。两个数组不同那么其至少有一个位置不同。
不同的重排可以得到相同的数组,我们先不考虑去重。
我们考虑从小到大加入\(a_i\),那么如果\(a_i\)插入到\(x, y\)两个元素之间,需要满足\(a_i \geq x - d, y \geq a_i - d\)。因为是从小到大加入,那么\(a_i \geq x - d\)一定满足。问题变为\([1, i - 1]\)里有多少\(a_j \geq a_i - d\)。那么可以用一个指针维护最小满足条件的\(j\)。就有\(i - j + 1\)中方案。
现在考虑去重,如果\(x\)有\(cnt_x\)个,那么就会产生\(cnt_x!\)个相同的数组。每个元素产生的方案会乘起来,于是需要把它们都除掉。
代码省略取模类。
点击查看代码
constexpr int P = 998244353;
using Z = MInt<P>;
struct Comb {
int n;
std::vector<Z> _fac;
std::vector<Z> _invfac;
std::vector<Z> _inv;
Comb() : n{0}, _fac{1}, _invfac{1}, _inv{0} {}
Comb(int n) : Comb() {
init(n);
}
void init(int m) {
if (m <= n) return;
_fac.resize(m + 1);
_invfac.resize(m + 1);
_inv.resize(m + 1);
for (int i = n + 1; i <= m; i++) {
_fac[i] = _fac[i - 1] * i;
}
_invfac[m] = _fac[m].inv();
for (int i = m; i > n; i--) {
_invfac[i - 1] = _invfac[i] * i;
_inv[i] = _invfac[i] * _fac[i - 1];
}
n = m;
}
Z fac(int m) {
if (m > n) init(2 * m);
return _fac[m];
}
Z invfac(int m) {
if (m > n) init(2 * m);
return _invfac[m];
}
Z inv(int m) {
if (m > n) init(2 * m);
return _inv[m];
}
Z binom(int n, int m) {
if (n < m || m < 0) return 0;
return fac(n) * invfac(m) * invfac(n - m);
}
} comb;
constexpr int N = 1e6;
int sum[N + 1];
void solve() {
int n, d;
std::cin >> n >> d;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
std::ranges::sort(a);
Z ans = 1;
for (int i = 0, j = 0; i < n; ++ i) {
while (j < i && a[i] - a[j] > d) {
++ j;
}
ans *= i - j + 1;
}
for (int i = 0; i < n; ++ i) {
int j = i;
while (j + 1 < n && a[i] == a[j + 1]) {
++ j;
}
ans /= comb.fac(j - i + 1);
i = j;
}
std::cout << ans << "\n";
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
int t = 1;
// std::cin >> t;
while (t -- ) {
solve();
}
return 0;
}

浙公网安备 33010602011771号