2024牛客暑期多校训练营5
B - 珑
首先要记得\(a=1\) 短边可以相邻,$b = 1 $ 长边可以相邻。
首先\(n m \equiv 1 \mod2\),一定无解,优先特判这种情况。
当\(a = 0, b = 1\)时,可以构造出$3\times 2 k, 2 \times 2 k $,可以用 \(2,3\)拼出任意行,所以只有$1 \times 2 k $ 无解
当\(a = 1 , b= 0\) 时,只能排成一排,也就是只有$1\times 2k $ 有解
当$a = 1 , b = 1 $,时,所有情况都合法。
当$a = 0 , b = 0 $ 是,就只有$n = 1 , m = 2 $ 和 $n = 2 , m = 1 $是合法的
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
using ldb = long double;
const i32 inf = INT_MAX / 2;
const i64 INF = LLONG_MAX / 2;
#define int i64
using vi = vector<int>;
void solve() {
int n, m, a, b;
cin >> n >> m >> a >> b;
bool flag = true;
if (n > m) swap(n, m);
if ((n * m) % 2 == 1) flag = false;
if (b == 0 and n != 1) flag = false;
if (a == 0 and n == 1 and m != 2) flag = false;
if (flag) cout << "Yes\n";
else cout << "No\n";
return;
}
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int T;
for (cin >> T; T; T--)
solve();
return 0;
}
E - 安
考虑\(a_i \ne b_i\)的情况
如果\(a_i > b_i\) ,则先手必胜。 因为当\(a_i = b_i\) 时,先手可以立即进行一次操作使得$a_i > b_i \(。因此一定是\)b$先变为0。
在考虑\(a_i = b_i\) 的情况。两个人可以各选择一半变为对自己更优的情况。
#include <bits/stdc++.h>
using namespace std;
using vi = vector<int>;
void solve(){
int n;
cin >> n;
vi a(n), b(n);
for(int i = 0; i < n; i ++)
cin >> a[i];
for(int i = 0; i < n; i ++)
cin >> b[i];
int cnt = 0, ans = 0;
for(int i = 0; i < n; i ++)
if(a[i] > b[i]) ans ++;
else if(a[i] == b[i]) cnt ++;
cout << (cnt + 1) / 2 + ans << "\n";
return ;
}
int main(){
ios::sync_with_stdio(false), cin.tie(nullptr);
int T;
cin >> T;
while(T --)
solve();
return 0;
}
H - 入
考虑到点数不多,我们可以直接暴搜。
我们可以找到一条最长链,然后链上的点递减,剩下的点赋值为无穷大就好了。
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
using ldb = long double;
const i32 inf = INT_MAX / 2;
const i64 INF = LLONG_MAX / 2;
#define int i64
using vi = vector<int>;
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n, m;
cin >> n >> m;
vector<vi> e(n + 1);
vi neighbour(n + 1);
for (int i = 1; i <= n; i++)
neighbour[i] |= (1ll << i);
for (int x, y; m; m--) {
cin >> x >> y;
e[x].push_back(y), neighbour[x] |= (1ll << y);
e[y].push_back(x), neighbour[y] |= (1ll << x);
}
int res = 0;
auto dfs = [&](auto &&dfs, int x, int d, int ban) -> void {
res = max(res, d);
for (int y: e[x]) {
if (ban & (1ll << y)) continue;
dfs(dfs, y, d + 1, ban | neighbour[x]);
}
};
for (int i = 1; i <= n; i++)
dfs(dfs, i, 1, 0);
cout << res;
return 0;
}
L - 知
可以想到要求是尽可能的平均,且只能从后向前拿。所以如果\(a_i < a_{i+1}\)就执行一次操作。
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
#define int i64
const int mod = 998244353;
using vi = vector<int>;
void solve(){
int n;
cin >> n;
vi a(n);
for(auto &i : a) cin >> i;
while(true) {
bool flag = false;
for(int i = 1; i < n; i ++)
if(a[i] > a[i-1]) a[i-1] ++, a[i] --, flag = true;
if(flag) continue;
else break;
}
i64 cnt = 1;
for(int i : a)
cnt = cnt * i % mod;
cout << cnt << "\n";
}
i32 main(){
ios::sync_with_stdio(false), cin.tie(nullptr);
int TC;
cin >> TC;
while(TC --)
solve();
return 0;
}