接着剤の精進日記

競プロでの精進や研究に関係したことを書いていきます。

AtCoder Beginner Contest 158(ABC158)

atcoder.jp

体感冷えだったけど微増だった
ハーフマラソン -> こどふぉ -> ABCで最初全然頭回ってなかったね

A - Station and Bus

最近似たようなのなかったっけ?
コードほとんど書き終わってからsetのほうが楽だったなーってなった
提出コード

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    string S;
    cin >> S;
    bool A = false; bool B = false;
    REP(i,3){
        if(S[i] == 'A') A = true;
        else B = true;
    }
    if(A && B) cout << "Yes" << endl;
    else cout << "No" << endl;
}

B - Count Balls

割り算を頑張る
提出コード

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll N, A, B;
    cin >> N >> A >> B;
    ll ans = 0;
    ll cnt = N / (A + B);
    ans += A * cnt;
    N -= cnt * (A + B);
    if(N > A) ans += A;
    else ans += N;

    cout << ans << endl;
}

C - Tax Increase

こういうのは取り敢えず全探索をすることを考える
雑に1万くらいまで見たけど最大を考えると2000も見れば十分(最大でも1000ちょっと)
提出コード

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    int A, B;
    cin >> A >> B;
    for(int i=1;i<=10101;i++){
        if((i * 8) / 100 == A && (i  / 10 == B)){
            cout << i << endl;
            return 0;
        }
    }
    cout << -1 << endl;
}

D - String Formation

DはdequeのD
本番でdeque使ったの地味に初めてかもしれない
先頭の要素と一番後ろの要素を高速に取得したいのでdequeを使うのが一番楽だと思う
最初「文字列の前後を反転」を先頭要素と一番後ろの要素swapだと思ってWAを吐いた(1敗)
提出コード

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    deque<char> dq;
    string S;
    cin >> S;
    REP(i,S.size()) dq.push_back(S[i]);
    int Q;
    cin >> Q;
    bool flg = true;//先頭
    while(Q--){
        int T;
        cin >> T;
        if(T == 1){
            flg ^= 1;
        }
        else{
            int F;
            char C;
            cin >> F >> C;
            if(F == 1){
                if(flg) dq.push_front(C);
                else dq.push_back(C);
            }
            else{
                if(flg) dq.push_back(C);
                else dq.push_front(C);
            }
        }
    }
    while(!dq.empty()){
        if(flg){
            cout << dq.front();
            dq.pop_front();
        }
        else{
            cout << dq.back();
            dq.pop_back();
        }
    }
    cout << endl;
}

E - Divisible Substring

本番中解けなかった
剰余を累積和みたいなのを考えて前からZero-Sum-Rangesみたいに解けそうとなる、サンプル3が合わない、コンテスト終了
実は剰余に罠があって、P == 2もしくはP == 5のときは場合分けが必要になってくる
それ以外のときは下から順に見ていってZero-Sum-Rangesっぽくやればおっけー
けんちょんさんの記事がわかりやすかったのでそちらを参考にしてください
drken1215.hatenablog.com

提出コード

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    int N, P;
    string S;
    cin >> N >> P >> S;

    map<ll, ll> mp;
    ll ans = 0;

    if(P == 2 || P == 5){
        for(int i=N-1;i>=0;i--){
            int d = S[i] - '0';
            if(P == 2 || P == 5){
                if(d % P == 0) ans += i + 1;
            }
        }
    }
    else{
        ll cur = 0;
        ll base = 1;
        mp[0]++;
        for(int i=N-1;i>=0;i--){
            int d = S[i] - '0';
            cur = cur + (base * d) % P;
            cur %= P;
            base *= 10;
            base %= P;
            mp[cur]++;
        }
        for(auto x : mp) ans += x.second * (x.second - 1) / 2;
    }
    cout << ans << endl;
}

F - Removing Robots

コンテスト後解説を覗いたら解けそうな気がしてきたので、頑張ってやってみます

おわりに

頭が回っていなくてBに結構時間かけてしまったのが痛い
DもWA出てすぐ気づいたけど誤読してて(ア)だった
Eは発想は悪くなかったと思うけど、詰めきれないままそれに固執しちゃったのが良くなかったね、反省