Codeforces Round 1034 (Div. 3)

发布于:2025-07-08 ⋅ 阅读:(13) ⋅ 点赞:(0)

A.Problem - A - Codeforces

关键点分析

  1. 选择条件:在选择的过程中,Bob 的选择受限于 Alice 选择的数字。具体来说,Bob 必须选择一个与 Alice 选择的数字 aaa 满足条件 a+b≡3(mod4)a + b \equiv 3 \pmod{4}a+b≡3(mod4)。这意味着给定 Alice 选择的 aaa,Bob 选择的 bbb 只能满足这个条件。

  2. 模4的分布:观察可以得出:

    • 每个数字 aaa 在 000 到 n−1n-1n−1 范围内,都有一个模 4 的余数值(即 a%4a \% 4a%4)。对于每个 aaa,Bob 需要根据 a+b≡3(mod4)a + b \equiv 3 \pmod{4}a+b≡3(mod4) 来选择 bbb。

    • 这个条件将模4的余数与另一个余数关联起来。具体来说:

      • 如果 a%4=0a \% 4 = 0a%4=0,则 b%4=3b \% 4 = 3b%4=3

      • 如果 a%4=1a \% 4 = 1a%4=1,则 b%4=2b \% 4 = 2b%4=2

      • 如果 a%4=2a \% 4 = 2a%4=2,则 b%4=1b \% 4 = 1b%4=1

      • 如果 a%4=3a \% 4 = 3a%4=3,则 b%4=0b \% 4 = 0b%4=0

  3. 胜负判断:考虑到 Alice 先手,游戏的结果与初始模4的分布有关。我们可以通过模拟这种选择过程来判断谁会先被卡住。

解题思路

  1. 模4的分布:可以通过计算每个数字 aaa 对 4 取余的分布情况,确定每个余数类别中有多少数字。通过模拟 Alice 和 Bob 的选择,我们可以确定谁会输掉游戏。

  2. 博弈的动态规划:每当 Alice 或 Bob 选择一个数字并擦去后,游戏的状态就会发生变化。我们可以使用动态规划来模拟这个过程,直到没有有效选择。

C

Problem - C - Codeforces

因为常规思想写出来会超时所以选择用预处理带动态规划的思想,通过预处理 避免重复计算,并利用 辅助数组 提供快速访问来优化时间复杂度。常见的优化手段还有 动态规划分治法滑动窗口 等。通过这类预处理的技巧,很多复杂度较高的问题可以被简化为线性时间复杂度,从而大大提高程序的效率。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int a[N];
int minpre[N],maxsu[N];
void solve()
{
    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    minpre[0]=a[0];
    for(int i=1;i<n;i++)
        minpre[i]=min(minpre[i-1],a[i]);
    maxsu[n-1]=a[n-1];
    for(int i=n-2;i>=0;i--)
        maxsu[i]=max(maxsu[i+1],a[i]);
    cout<<1;
    for(int i=1;i<n-1;i++)
    {
        bool f1=a[i]<minpre[i-1];
        bool f2=a[i]>maxsu[i+1];
        if(f1 || f2) cout<<1;
        else cout<<0;
    }
    cout<<1<<endl;
}
int main()
{
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

D:二进制字符串博弈判断器

Problem - D - Codeforces

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
void solve()
{
    int n,k;
    string s;
    cin>>n>>k>>s;
    int cnt=0;
    for(auto a:s)
        if(a=='1')
            cnt++;
    cout<<(cnt<=k || n<2*k ? "Alice" :"Bob")<<endl;
}
int main()
{
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}
✅ 第一种情况:cnt <= k

这是最简单直接的:

  • Alice 可以选择任意子序列(不要求连续),长度为 k

  • 如果字符串中总共只有 ≤k1,Alice 第一轮就可以全选中这些 1,直接全部清零,立即获胜 ✅。


✅ 第二种情况:n < 2 * k

这个判断稍微复杂一点,需要从 博弈角度分析

思路如下:
  • Alice 每轮可以“任意选”k个字符变成 0(子序列,任意位置)

  • Bob 每轮只能“连续选”k个字符变成 1(子串,必须连续)

  • 现在,如果总长度 n < 2*k,Bob 的能力会变得 局限,他能影响的空间变小。

举例:
  • Bob能操作的连续子串,一共只有 (n - k + 1) 种可能。

  • Alice可以任意选择非连续字符的位置来置 0她的覆盖能力远远强于 Bob

所以当 n < 2*k 时,Alice 有足够的操作空间可以克制 Bob 的行为,最终能把全部字符变成 0,从而赢得胜利。


网站公告

今日签到

点亮在社区的每一天
去签到