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

### コンテスト名
AtCoder Beginner Contest 380

### コンテストURL
https://atcoder.jp/contests/abc380

### 開催日
2024/11/16 21:00-22:40

---

## [A: 123233](https://atcoder.jp/contests/abc380/tasks/abc380_a)
**解法**
- 問題文通りに判定する
```cpp: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](https://atcoder.jp/contests/abc380/tasks/abc380_b)
**解法**
- 文字列を前から順番にたどり、連続する `-` の数を記録する 
```cpp: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](https://atcoder.jp/contests/abc380/tasks/abc380_c)
**解法**
- $K-1$ 番目の `1` の塊の最後の位置、 $K$ 番目の `1` の塊の最初の位置、 $K$ 番目の `1` の塊の最後の位置を求める
```cpp: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](https://atcoder.jp/contests/abc380/tasks/abc380_d)
**解法**
- 文字は文字列 $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` でキャストする
```cpp: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;
}
```