返回顶部

Codeforces Round #659 (Div. 2)【ABCD】(题解)

涵盖知识点:思维、博弈

比赛链接:传送门

A - Common Prefixes

题意: 构造\(n+1\)个字符串使得第\(i\)个和第\(i+1\)个字符串的最长公共前缀的长度为\(a_i\)
题解: 一开始全a,后面随便改一改。
Accept Code:

#include <bits/stdc++.h>
using namespace std;
const int maxn=110;
int a[maxn];
int main(){
    int t;cin>>t;
    while(t--){
        int n;cin>>n;
        for(int i=1;i<=n;i++)cin>>a[i];
        string s(55,'a');
        cout<<s<<"\n";
        for(int i=1;i<=n;i++){
            s[a[i]]++;
            if(s[a[i]]=='z'+1)s[a[i]]='a';
            cout<<s<<"\n";
        }
    }
    return 0;
}

B2 - Koa and the Beach (Hard Version)

题意: 共有\(n\)片海域,初始深度分别给定。潮汐会以\(2k\)为周期上下波动影响深度,前\(k\)秒以\(1m/s\)的速度加深,后\(k\)秒以\(1m/s\)速度变浅。每一秒都可以选择呆在当前海域或前往下一海域,但是当深度大于\(l\)时就会淹死。问能否到达最后的终点。
题解: 确定所有深度加\(k\)小于等于\(l\)的点为安全区,可以在任意的安全区停留任意长的时间。然后尽可能选择最早的不会淹死的时间进入下一节点。
Accept Code:

#include <bits/stdc++.h>
using namespace std;
const int maxn=3e5+10;
int d[maxn];
int main(){
    int t;cin>>t;
    while(t--){
        int n,k,l;
        cin>>n>>k>>l;
        vector<int> safe={0};
        for(int i=1;i<=n;i++){
            cin>>d[i];
            if(d[i]+k<=l)safe.push_back(i);
        }
        safe.push_back(n+1);
        bool flag=true;
        for(int i=1;i<safe.size()&&flag;i++){
            int tide=k,down=-1;
            for(int j=safe[i-1]+1;j<safe[i];j++){
                tide+=down;
                if(down==-1)tide-=max(0,d[j]+tide-l);
                if(tide<0||d[j]+tide>l){flag=false;break;}
                if(tide==0)down=1;
            }
        }
        puts(flag?"Yes":"No");
    }
    return 0 ;
}

C - String Transformation 1

题意: 给定两个字符串,每次可以选择一个字母然后把\(a\)中所有的那个字母变为比他大的另一个字母,问最少几次能把\(a\)变为\(b\)
题解: 贪心,直接按照需求从小到大模拟一遍。
Accept Code:

#include <bits/stdc++.h>
using namespace std;
const int maxn=20;
int c[maxn][maxn];
int main(){
    int t;cin>>t;
    while(t--){
        int n;cin>>n;
        string a,b;
        cin>>a>>b;
        memset(c,0,sizeof c);
        int ans=0;
        for(int i=0;i<n;i++){
            if(a[i]>b[i]){
                puts("-1");
                goto st;
            }
            c[a[i]-'a'][b[i]-'a']++;
        }
        for(int i=0;i<19;i++){
            int tmp=21;
            for(int j=i+1;j<20;j++){
                if(c[i][j])tmp=min(tmp,j);
            }
            if(tmp!=21){
                ans++;
                for(int j=i+1;j<20;j++){
                    c[tmp][j]+=c[i][j];
                }
            }
        }
        cout<<ans<<"\n";
        st:;
    }
    return 0;
}

D - GameGame

题意: 博弈,两人拿数,异或值大的胜。
题解: 若所有值的异或值\(sum\)\(0\)则平局。否则只要判断\(sum\)的最高位。问题转化为谁拿走了奇数个最高位的数字就获胜。如果数字的个数为偶数个,那么最后一次拿的人是后手,显然先手必胜,只要先取一个符合要求的接下来模仿对手即可。接下来考虑数字个数为奇数的情况,若含最高位的数字个数对\(4\)取模结果为\(1\),那么先手可以先取一个含最高位的数字,接下来模仿对手的操作。否则先后手交换。
Accept Code:

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn],cnt[2];
int main(){
    int t;cin>>t;
    while(t--){
        int n;cin>>n;
        int sum=0;
        for(int i=0;i<n;i++){
            cin>>a[i];
            sum^=a[i];
        }
        if(sum==0){
            puts("DRAW");
            continue;
        }
        int b=1<<(31-__builtin_clz(sum));
        memset(cnt,0,sizeof cnt);
        for(int i=0;i<n;i++)cnt[bool(a[i]&b)]++;
        if(cnt[1]%4==1||n%2==0)puts("WIN");
        else puts("LOSE");
    }
    return 0;
}
posted @ 2020-07-26 21:16  Charles1999  阅读(297)  评论(0编辑  收藏  举报