【CodeForces训练记录】Codeforces Round 1034 (Div. 3)

训练情况

image

A题

首先我们可以将 \(0 \sim n-1\) 全部对 4 取模,那么 Bob 问题就转化成在 Alice 选完之后再找一个数字和为 4 即可,我们发现 \(0 \sim n-1\) 取模 4 后为一个 0,1,2,3 的循环节,对于 Alice 选 0,Bob 选 3,Alice 选 1,Bob 选 2,Alice 选 2,Bob 选 1,Alice 选 3,Bob 选 0,对于单个循环节一定是 Bob 必胜,那么对于多出循环节的部分,Bob 一定找不到对应的数字和为 4,所以 Alice 必胜,综上如果 n 是 4 的倍数则 Bob 必胜,反之 Alice 必胜

点击查看代码
#include <bits/stdc++.h>
// #define int long long
#define endl '\n'

using namespace std;

void solve(){
    int n; cin>>n;
    n--;
    n%=4;
    if(n == 0) cout<<"Alice"<<endl;
    else if(n == 1) cout<<"Alice"<<endl;
    else if(n == 2) cout<<"Alice"<<endl;
    else cout<<"Bob"<<endl;
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
    int T; cin>>T; while(T--)
    solve();
    return 0;
}

B题

题目问是否存在一种情况,那么我们贪心考虑,只要随机的两个人没有选到目标的棋手,则永远不会被淘汰掉(除非只剩下两个人 1v1),所以当 k = 1 的时候目标棋手的实力必须是最大值才能剩下,反之则不可能,对于 k > 1 的情况,只要随机出的两人没有目标棋手,则目标棋手则一直不会被淘汰,分类讨论即可

点击查看代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'

using namespace std;

void solve(){
    int n,j,k; cin>>n>>j>>k;
    vector<int> a(n + 1);
    int ma = 0;
    for(int i = 1;i<=n;i++) cin>>a[i],ma = max(ma,a[i]);
    if(k == 1 && ma != a[j]) cout<<"NO"<<endl;
    else cout<<"YES"<<endl;
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
    int T; cin>>T; while(T--)
    solve();
    return 0;
}

C题

替换某个数为前缀的最小值,或者后缀的最大值,我们首先维护前缀最小值和后缀最大值,反复操作前缀最小等效一次前缀最小,后缀最大同理,所以至多三次有效操作:一次前缀最小,一次后缀最大,然后前者消除后者或者后者消除前者,所以一旦相等则必然存在一种操作方法能最终剩下那个数

点击查看代码
#include <bits/stdc++.h>
// #define int long long
#define endl '\n'

using namespace std;

void solve(){
    int n; cin>>n;
    vector<int> a(n + 1);
    for(int i = 1;i<=n;i++) cin>>a[i];
    vector<int> p(n + 3),s(n + 3);
    p[0] = INT_MAX;
    for(int i = 1;i<=n;i++) p[i] = min(p[i-1],a[i]);
    for(int i = n;i;i--) s[i] = max(s[i+1],a[i]);
    // for(int i = 1;i<=n;i++) cout<<p[i]<<" "; cout<<endl;
    // for(int i = 1;i<=n;i++) cout<<s[i]<<" "; cout<<endl;
    for(int i = 1;i<=n;i++){
        if(a[i] == p[i] || a[i] == s[i]) cout<<1;
        else cout<<0;
    }
    cout<<endl;
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
    int T; cin>>T; while(T--)
    solve();
    return 0;
}

D题

首先对于子序列修改和子串修改,想要最大化子序列修改的贡献,我们必然选择不连续字符修改(如果选择连续的字符修改,子串修改可以再覆盖回来,做了约等于没做,除非子序列直接全部改成 0),我们考虑修改一个位置,之后空 k-1 个位置,再修改剩下连续的 k-1 个字符,例如 n = 5,k = 3 的情况

1 1 1 1 1
0 1 1 0 0

则这样子串修改为了最优必然会修改 0 多的部分,左边就能多出一个 0,接下来以此类推,直到左边连续的 0 为 k - 1 个的时候,在某一次子序列修改就能把所有的 1 修改成 0 答案为 YES,否则一旦数组过长左边的 0 会被一次子串修改就覆盖掉,就会陷入无限操作的情况,答案为 NO,边界条件为 n = 2k

这样子串修改则必须将会

点击查看代码
#include <bits/stdc++.h>
// #define int long long
#define endl '\n'

using namespace std;

void solve(){
    int n,k; cin>>n>>k;
    string s; cin>>s;
    int cnt = 0;
    for(int i = 0;i<n;i++){
        if(s[i] == '1') cnt++;
    }
    if(cnt <= k){
        cout<<"Alice"<<endl;
        return;
    }
    if(n>=k*2) cout<<"Bob"<<endl;
    else cout<<"Alice"<<endl;
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
    int T; cin>>T; while(T--)
    solve();
    return 0;
}
```cpp
</details>
posted @ 2025-07-02 01:12  MNNUACM_2024ZY  阅读(127)  评论(0)    收藏  举报