牛客小白月赛112
A. 智乃的天平
点击查看代码
void solve() {
int a, b, w;
std::cin >> a >> b >> w;
if (a == w || b == w || a + b == w || a + w == b || b + w == a) {
std::cout << "Yes\n";
} else {
std::cout << "No\n";
}
}
B. 智乃爬山
循环判断取最大值。
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
int ans = -1;
for (int i = 1; i + 1 < n; ++ i) {
if (a[i] > a[i - 1] && a[i] > a[i + 1]) {
ans = std::max(ans, a[i] - (a[i - 1] + a[i + 1]) / 2);
}
}
std::cout << ans << "\n";
}
C. 智乃放球
题意:\(n\)个球\(m\)个桶,你要把这些球放到这些桶里,假设第\(i\)个桶放了\(cnt_i\)个球,那么会变成\(cnt_i \% k\)个球。你要使得总球数恰好为\(q\)。
一个桶里最多有\(k-1\)个球,那么如果\((n-1)\times m < q\)无解。
那么我们贪心的每个桶放\(k-1\)个球,然后剩下的\(n \% (k-1)\)个球单独放一个桶。那么还剩下\(n-q\)个球,显然这些球不可以改变总球数,那么\(n=q \% k = 0\)。
点击查看代码
void solve() {
int n, m, k, q;
std::cin >> n >> m >> k >> q;
if (k == 1) {
std::cout << "No\n";
return;
}
int cnt = (q + k - 2) / (k - 1);
if (m < cnt) {
std::cout << "No\n";
return;
}
if ((n - q) % k) {
std::cout << "No\n";
return;
}
std::cout << "Yes\n";
}
D. 智乃的“K”叉树
题意:给你一棵树,选一个点作为根,使得儿子最多的点的儿子数最少。
假设没有根,那么我们选\(u\)为根,根的度数不变,其它的的度数减一。那么把所有点的度数存进\(multiset\),然后枚举作为根的节点,它的度数和剩下点的最大度数减一的最大值就是最多的儿子数。
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> deg(n);
for (int i = 1; i < n; ++ i) {
int u, v;
std::cin >> u >> v;
-- u, -- v;
++ deg[u];
++ deg[v];
}
std::multiset<int> s;
for (int i = 0; i < n; ++ i) {
s.insert(deg[i]);
}
int k = 1e9, ans = 0;
for (int i = 0; i < n; ++ i) {
s.extract(deg[i]);
if (std::max(deg[i], *s.rbegin() - 1) < k) {
k = std::max(deg[i], *s.rbegin() - 1);
ans = i;
}
s.insert(deg[i]);
}
std::cout << k << " " << ans + 1 << "\n";
}
E. 智乃的“凑数”题(Easy Version)
题意:\(n\)个数,\(m\)个询问,把\(n\)个数分为三部分,价值为第一部分的和与第二部分的和的乘积,第三部分则抛弃,求使得价值恰好为\(x\)的方案。
考虑\(dp\),\(f[i][j][k]\)表示前\(i\)个数第一部分的和为\(i\),第二部分的和为\(j\)是否可行,然后\(pre[i][j][k]\)记录前面转移过来的状态。
点击查看代码
void solve() {
int n, m;
std::cin >> n >> m;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
const int N = 101;
std::vector f(n + 1, std::vector(N, std::vector<int>(N)));
std::vector pre(n + 1, std::vector(N, std::vector<std::pair<int, int>>(N)));
f[0][0][0] = 1;
for (int i = 0; i < n; ++ i) {
for (int j = 0; j < N; ++ j) {
for (int k = 0; k < N; ++ k) {
if (!f[i][j][k]) {
continue;
}
f[i + 1][j][k] = f[i][j][k];
pre[i + 1][j][k] = pre[i][j][k];
if (j + a[i] < N) {
f[i + 1][j + a[i]][k] = 1;
pre[i + 1][j + a[i]][k] = {j, k};
}
if (k + a[i] < N) {
f[i + 1][j][k + a[i]] = 1;
pre[i + 1][j][k + a[i]] = {j, k};
}
}
}
}
while (m -- ) {
int x;
std::cin >> x;
std::vector<int> A, B;
for (int v = 1; v * v <= x; ++ v) {
if (x % v == 0) {
if (f[n][v][x / v]) {
int i = n, j = v, k = x / v;
while (i) {
auto & [prej, prek] = pre[i][j][k];
if (prej != j) {
A.push_back(j - prej);
} else if (prek != k) {
B.push_back(k - prek);
}
-- i;
j = prej;
k = prek;
}
break;
}
}
}
if (A.empty() && B.empty()) {
std::cout << "No\n";
} else {
std::cout << "Yes\n";
std::cout << A.size() << " " << B.size() << "\n";
for (auto & x : A) {
std::cout << x << " ";
}
std::cout << "\n";
for (auto & x : B) {
std::cout << x << " ";
}
std::cout << "\n";
}
}
}