VP Educational Codeforces Round 50 (Rated for Div. 2)
A. Function Height
题意:\(n\)个数给他们赋值,使得和恰好为\(k\), 求其中的最大值最小。
点击查看代码
void solve() {
i64 n, k;
std::cin >> n >> k;
std::cout << (k + n - 1) / n << "\n";
}
B. Diagonal Walking v.2
题意:从\((0, 0)\)走到\((n, m)\)恰好走\(k\)步,可以走八个方向。求最多可以走几条斜边。
首先要发现,到了\((n, m)\)后如果剩下步数是偶数可以一直斜着来回走。
假设\(n >= m\),先斜着走\(m\)步到\((m, m)\)。
那么如果\(n - m\)是奇数,那么如果剩下奇数步,我们向上走一步,就变成了剩下步数和到终点距离都是偶数,于是剩下步数都可以走斜边。如果剩下步数是偶数,我们可以向左或者向右走一步,然后斜着向上一步,剩下步数和到终点距离就都是偶数。于是这个情况答案就是\(k-1\)。
否则如果\(n - m\)是偶数,如果剩下奇数步,则我们只能通过水平移动一次向上移动一次来缓冲,这样少了两步,答案是\(k-2\),否则就是\(k\)。
点击查看代码
void solve() {
i64 n, m, k;
std::cin >> n >> m >> k;
if (n < m) {
std::swap(n, m);
}
if (k < n) {
std::cout << -1 << "\n";
return;
}
int d = k - m;
if (n - m & 1) {
if (d & 1) {
std::cout << k - 1 << "\n";
} else {
std::cout << k - 1 << "\n";
}
} else {
if (d & 1) {
std::cout << k - 2 << "\n";
} else {
std::cout << k << "\n";
}
}
}
C. Classy Numbers
题意:求\([L, R]\)这个区间有多少数数位中非零数不超过三。
数位\(dp\)。\(f[i][cnt]\)表示到第\(i\)为有\(cnt\)个非零数的答案。
点击查看代码
void solve() {
i64 l, r;
std::cin >> l >> r;
std::vector f(20, std::array<i64, 4>{-1, -1, -1, -1});
auto dp = [&](i64 n) -> i64 {
std::string s;
do {
s += (char)(n % 10 + '0');
n /= 10;
} while (n);
auto dfs = [&](auto & self, int u, int cnt, bool limit) -> i64 {
if (cnt > 3) {
return 0;
}
if (u == -1) {
return 1;
}
if (f[u][cnt] != -1 && !limit) {
return f[u][cnt];
}
int up = limit ? s[u] - '0' : 9;
i64 res = 0;
for (int i = 0; i <= up; ++ i) {
res += self(self, u - 1, cnt + (i != 0), limit && i == up);
}
if (!limit) {
f[u][cnt] = res;
}
return res;
};
return dfs(dfs, (int)s.size() - 1, 0, true);
};
std::cout << dp(r) - dp(l - 1) << "\n";
}
D. Vasya and Arrays
题意:给你两个数组,把他们划分成\(k\)份,使得从左到右对应的每一份和相等。使得\(k\)最大。
模拟,记录两个和以及加到了哪个数,然后讨论哪个和小就加哪个数组的数。
点击查看代码
void solve() {
int n, m;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
std::cin >> m;
std::vector<int> b(m);
for (int i = 0; i < m; ++ i) {
std::cin >> b[i];
}
int ans = 0;
int i = 0, j = 0;
i64 sa = 0, sb = 0;
while (i < n || j < m) {
if (sa < sb) {
if (i == n) {
break;
}
sa += a[i ++ ];
} else if (sa > sb) {
if (j == m) {
break;
}
sb += b[j ++ ];
} else {
if (i == n || j == m) {
break;
}
if (a[i] > b[j]) {
sa = a[i ++ ];
} else {
sb = b[j ++ ];
}
}
if (sa == sb) {
++ ans;
sa = sb = 0;
}
}
if (i != n || j != m || sa != sb) {
std::cout << -1 << "\n";
} else {
std::cout << ans << "\n";
}
}