Codeforces Round 1028 (Div. 2) (A ~ C)
A. Gellyfish and Tricolor Pansy
博弈
题意:
水母和花花决斗,他们分别有他们各自的骑士且他们四个有各自的HP,只有各自的骑士可以攻击并且只能攻击对方或者对方的骑士,看谁先G,水母先手
思路:
决定游戏的关键是HP最小的那个,骑士和主人谁先G都代表失败,所以只要看HP最小的那个在哪一方就可以,记得要考虑最小HP各自都有,那么就是水母胜(先手的原因)
代码:
void solve()
{
int a,b,c,d;
cin >> a >> b >> c >> d;
int min_a = min(a,c),min_b = min(b,d);
cout << (min_a >= min_b ? "Gellyfish" : "Flower") << '\n';
}
B. Gellyfish and Baby's Breath
贪心,数学
题意:
给你两个\(0\)到\(n - 1\)排列,让你求\(r_i = max_{j=0}^i 2^{a_j} + 2^{b_{i-j}}\), 求出\(r\)序列,结果\(mod998244353\)
思路:
对于每一个\(r_i\),起决定作用的是\(2\)的幂次最大的那个也就是\(p\)排列和\(q\)排列\(0\) ~ \(i\)中的\(max\),所以只需分别在两个排列中维护各自的最大值即可,然后比较一下选最大的即可
代码:
void solve()
{
int n;
cin >> n;
vector<int> p(n),q(n);
for(int i = 0; i < n; i ++) cin >> p[i];
for(int i = 0; i < n; i ++) cin >> q[i];
auto qmi = [&](int a,int k) -> int
{
int res = 1;
while(k)
{
if(k & 1) res = res * a % mod;
a = a * a % mod;
k >>= 1;
}
return res;
};
auto get = [&](int a,int b) -> int
{
return (qmi(2,a) % mod + qmi(2,b) % mod) % mod;
};
array<int,2> maxv;
vector<int> res(n);
for(int i = 0; i < n; i ++)
{
if(i == 0)
{
maxv[0] = maxv[1] = 0;
res[i] = get(p[i],q[i]);
continue;
}
if(p[i] > p[maxv[0]]) maxv[0] = i;
if(q[i] > q[maxv[1]]) maxv[1] = i;
if(p[maxv[0]] == q[maxv[1]]) res[i] = get(p[maxv[0]],max(q[i - maxv[0]],p[i - maxv[1]]));
else
{
if(p[maxv[0]] > q[maxv[1]]) res[i] = get(p[maxv[0]],q[i - maxv[0]]);
else res[i] = get(q[maxv[1]],p[i - maxv[1]]);
}
}
for(auto x : res) cout << x << ' ';
cout << '\n';
}
C. Gellyfish and Flaming Peony
动态规划 数论
此题还可用BFS解决
题意:
给了一个数组,每次操作选择两个数使得第一个数修改为两数的\(GCD\),问最少需要多少次操作可以使得整个数组中的元素相同
思路:
分析可得最后数组元素一定是所有元素的\(GCD\)
- 数组中本身就存在这个数,那么答案就是所有数组中与这个\(answer\)不同的个数,因为每次操作只能修改一个数
- 数组中不含这个\(answer\),那么我就需要找出数组中能构造出这个\(answer\)的所需最少的数组元素的个数
第一种情况判断一下可以直接算出就是\(n\) - 最小元素的个数(如果答案存在那么这个答案一定是数组中的最小元素)
第二种情况考虑用动态规划解决:
- 状态表示\(f[i][j]\):表示前\(i\)个数构造出GCD为\(i\)所需元素的最小数量
- 状态计算:\(f[i][gcd(a[i],j)] = min(f[i][gcd(a[i],j)],f[i - 1][j] + 1)\)
最后使用滚动数组优化一下内存可以通过
代码:
void solve()
{
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
int d = 0;
for (auto & x : a) {
d = std::gcd(x, d);
}
if (*std::min_element(a.begin(), a.end()) == d) {
std::cout << n - std::ranges::count(a, d) << "\n";
return;
}
const int inf = 1e9, N = 5000;
std::vector f(N + 1, inf);
f[0] = 0;
for (int i = 0; i < n; ++ i) {
for (int j = 1; j <= N; ++ j) {
f[std::gcd(a[i], j)] = std::min(f[std::gcd(a[i], j)], f[j] + 1);
}
f[a[i]] = 1;
}
std::cout << f[d] - 1 + n - 1 << "\n";
}