🔵

【ABC380】AtCoder Beginner Contest 380【C++】

2024/11/17に公開

コンテスト名

AtCoder Beginner Contest 380

コンテストURL

https://atcoder.jp/contests/abc380

開催日

2024/11/16 21:00-22:40


A: 123233

解法

  • 問題文通りに判定する
ABC380A.cpp
#include <iostream>
#include <string>
using namespace std;

int main(){
    string s;
    cin >> s;

    int a = 0, b = 0, c = 0;
    for(int i=0; i<s.size(); i++){
        if(s[i]=='1'){
            a++;
        }else if(s[i]=='2'){
            b++;
        }else if(s[i]=='3'){
            c++;
        }
    }

    if(a==1 && b==2 && c==3){
        cout << "Yes" << endl;
    }else{
        cout << "No" << endl;
    }

    return 0;
}

B: Hurdle Parsing

解法

  • 文字列を前から順番にたどり、連続する - の数を記録する
ABC380B.cpp
#include <iostream>
#include <vector>
using namespace std;

int main(){
    string s;
    cin >> s;

    vector<int> A;
    int cnt = 0;
    for(int i=1; i<s.size(); i++){
        if(s[i]=='|'){
            A.push_back(cnt);
            cnt = 0;
        }else{
            cnt++;
        }
    }

    for(int i=0; i<A.size(); i++){
        if(i){
            cout << " ";
        }
        cout << A[i];
    }
    cout << endl;

    return 0;
}

C: Move Segment

解法

  • K-1 番目の 1 の塊の最後の位置、 K 番目の 1 の塊の最初の位置、 K 番目の 1 の塊の最後の位置を求める
ABC380C.cpp
#include <iostream>
#include <string>
using namespace std;

int main(){
    int n, k;
    cin >> n >> k;

    string s;
    cin >> s;
    
    int pre_last, first, last = n-1;
    int cnt = 0, sum = 0;
    for(int i=0; i<s.size(); i++){
        if(s[i]=='0'){
            if(sum==k){
                last = i - 1;
            }
            cnt = 0;
        }else{
            if(cnt==0){
                sum++;
            }
            if(sum==k-1){
                pre_last = i;
            }
            if(cnt==0 && sum==k){
                first = i;
            }
            cnt++;
        }
    }

    for(int i=0; i<=pre_last; i++){
        cout << s[i];
    }
    for(int i=first; i<=last; i++){
        cout << s[i];
    }
    for(int i=pre_last+1; i<first; i++){
        cout << s[i];
    }
    for(int i=last+1; i<n; i++){
        cout << s[i];
    }
    cout << endl;

    return 0;
}

D: Strange Mirroring

解法

  • 文字は文字列 S の繰り返しであるため、 K_i 文字目の文字は ((K_i-1) \bmod |S|) + 1 文字目と同じである
  • 大文字小文字は、 K_i 文字目の文字が j 個目の文字列に属するとすると、 j-1 を二進数表記したときの 1 の個数の偶奇で判定する
    • j-1 を二進数表記したときの 1 の個数が偶数の場合、元の文字列 S と同じ大小
    • j-1 を二進数表記したときの 1 の個数が奇数の場合、元の文字列 S と反対の大小
  • 二進数表記したときの 1 の個数は __builtin_popcount() ではなく、 __builtin_popcountll() で求めることに注意する
  • C++20 の popcount() では unsigned long long でキャストする
ABC380D.cpp
#include <iostream>
#include <vector>
#include <bit>
using namespace std;

int main(){
    string s;
    cin >> s;

    int q;
    cin >> q;

    int n = s.size();

    vector<long long int> K(q);
    for(int i=0; i<q; i++){
        cin >> K[i];
        K[i]--;
    }

    for(int i=0; i<q; i++){
        if(i){
            cout << " ";
        }

        int cnt = __builtin_popcountll(K[i]/n);
        int x = K[i]%n;

        char c = s[x];
        if(cnt%2==0){
            cout << c;
        }else{
            if(islower(c)){
                cout << (char)toupper(c);
            }else{
                cout << (char)tolower(c);
            }
        }
    }
    cout << endl;

    return 0;
}

Discussion