Codeforces Round 1034 (Div. 3)

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

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

cpp 复制代码
#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,从而赢得胜利。

E.频率统计 + mex + 分类 + set维护

Problem - E - Codeforces

复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
#define ll long long int;
void solve()
{
    int n;
    cin>>n;
    vector<int> a(n);
    unordered_map<int,int> cnt;
    unordered_map<int,vector<int>> ss;
    int mx=0;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        cnt[a[i]]++;
        while(cnt.find(mx)!=cnt.end())
            mx++;
    }
    for(pair<int,int> p:cnt)
    {
        ss[p.second].push_back(p.first);
    }
    set<int> res;
    res.insert(mx);
    for(int k=0;k<=n;k++)
    {
        res.erase(n-k+1);
        for(int i:ss[k])
        {
            if(i<=min(n-k,mx))
                res.insert(i);
        }
        cout<<res.size()<<' ';
    }
    cout<<endl;
    
}
int main()
{
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

核心思路:

1.MEX是由出现频率控制的

2.某个值是否能成为MEX,取决于它之前的值是否都出现过,而他本身没有出现

3.对于每个频率f,记录有哪些值是出现了f次的,用ss[f]

4.模拟删掉k个元素时,某些数会"从数组中消失"或"频率降低"->会影响MEX值

变量含义解释:

unordered_map<int,int> cnt; // 记录每个数出现的次数

unordered_map<int,vector<int>> ss; // 每个频率对应出现了该频率的所有数

int mx = 0; // mx 表示初始时数组的 MEX

分类出现频率(核心)

for(pair<int,int> p:cnt)
{
ss[p.second].push_back(p.first);
}
这一步将所有数按频率分类,例如:
cnt = {
0: 2次,
1: 2次,
2: 1次
}
会得到:
ss[2] = [0,1]
ss[1] = [2]

相关推荐
不修×蝙蝠6 小时前
设计模式深度解析:单例、工厂、适配器与代理模式
单例模式·设计模式·代理模式·适配器模式·工厂
vvilkim1 天前
深入理解设计模式之代理模式:原理、实现与应用
设计模式·代理模式
小指纹1 天前
巧用Bitset!优化dp
数据结构·c++·算法·代理模式·dp·bitset
哪里不会点哪里.2 天前
代理模式:控制对象访问
java·代理模式
JouJz4 天前
设计模式之代理模式:掌控对象访问的优雅之道
java·spring·设计模式·系统安全·代理模式
饕餮争锋4 天前
设计模式笔记_结构型_代理模式
笔记·设计模式·代理模式
络74 天前
Java4种设计模式详解(单例模式、工厂模式、适配器模式、代理模式)
单例模式·设计模式·代理模式·适配器模式·工厂模式
咖啡进修指南4 天前
代理模式——Java
java·代理模式
不知疲倦的仄仄4 天前
2025Nginx最新版讲解/面试
nginx·代理模式·proxy模式