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";
}
posted @ 2025-08-24 10:54  Gabriel_7  阅读(16)  评论(0)    收藏  举报