u_sho競プロぶろぐ

21歳。みゃーくぴとぅ。ゆる~く続けますたぶん。  デザイン変えました(2019/2/25)これでいきます

AtCoder Beginner Contest 152

精進をサボってコンテストに出ていたのですが,このままでは「C o n t e s t a n t 笑」って感じなので,久々に記事を書いてやる気の足しにしようと思いました。

AtCoder Scores の精進グラフ
コンテスト以外で問題を解かなくなって早1年の図

A - AC or WA

解説するようなことはないんですが,あまりにも書いていなさすぎて cin << n とかやって CE を出していました😓
対策として VSCode で赤線出るようにしました。

#include<bits/stdc++.h>
const std::string ans[2] = { "No\n", "Yes\n" };

int main() {
    using namespace std;
    int n, m;
    cin >> n >> m;
    cout << ans[n == m] << endl;
    return 0;
}

一応注目は二行目の const string ans です。ans は使いがちな名前なのでちょっと怖い感じもしますが,long long ans 等の他の型の ans とは区別されるのでテンプレに入れました。
あと 575; (ユージング・ネームスペース・エスティーディ/スタンダード)は main の中に書くことにしました。グローバルをあんまり汚したくなくなってきたためです。

B - Comparing Strings

辞書順ってことは,要は数字の若い方(min(a, b))を出力すればいいんですね😆
このとき max(a, b) 個連続させて出力させるのが肝要ですたぶん。

#include<bits/stdc++.h>
int main() {
    using namespace std;
    int a, b;
    cin >> a >> b;

    // min(a,b)をmax(a,b)回出力する
    for (int i = 0; i < max(a,b); i++) cout << min(a,b);
    cout << endl;
    return 0;
}

rep マクロはあまり使わなかったので廃止しました。
私は ij を間違える回数よりも,rep のフォーマットに沿わない for の書き方をする回数が多かったです。

C - Low Elements

数列 \{P\} 中のある数 P_i について,それより左にある(添字が若い)全ての数よりも小さいかどうかを判定できれば,あとは数えるだけですね。
判定は, P_0 から P_{i-1} における最小値と比較してあげればOKです。

#include<bits/stdc++.h>
const std::string ans[2] = { "No\n", "Yes\n" };

int main() {
    using namespace std;
    int n;
    cin >> n;
    vector<int> P;
    for (int i = 0; i < n; i++){
        int p;
        cin >> p;
        P.push_back(p);
    }

    int min_p = P[0];
    int ans = 1;
    for (int i = 1; i < n; i++){
        if (P[i] < min_p) { // 比較してるとこ
            min_p = P[i]; // 更新を忘れない
            ans++; // 数える
        }
    }
    cout << ans << endl;
    return 0;
}

string ans がちゃんと無視されて,int ansが意図した動きをしています🤗🤗🤗
vector の入力のところで cin >> p[i] ってやっちゃう癖をなんとかしたいですね。これでパフォを300ほど落としています。
テンプレに operator>>(istream, vector)オーバーロードを入れてもいいかもしれません。

D - Handstand 2

よく耳にする「桁DP」というものだそうです。適当に実装したやつに名前がついていると嬉しくなっちゃいますね

#include<bits/stdc++.h>
using ll = long long;

int main() {
    using namespace std;
    int n;
    cin >> n;

    int match[10][10]; // match[先頭の数字][末尾の数字]
    fill(match[0], match[10], 0); // 初期化
    for (int i = 1; i <= n; i++){
        int d = i<10 ? 1 : i<100 ? 10 : i<1000 ? 100 : i<10000 ? 1000 : i <100000 ? 10000 : 100000; // 桁数
        int s = (i<10) ? i : (i / d); // 先頭の数字
        int e = i % 10; // 末尾の数字
        match[s][e]++;
    }
    ll ans = 0LL;
    for (int i = 1; i < 10; i++){
        for (int j = i; j < 10; j++){
            ans += 2 * match[i][j] * match[j][i]; // 2! = 2
            if (j==i) ans -= match[i][j] * match[i][j]; // (1,1)と(1,1)などは重複しているので引く
        }
    }

    cout << ans << endl;
    return 0;
}

コンテスト中は,桁数を求めるところで log10 を使っていたのですが,色々やらかしてしまって提出できませんでした...
終了してからこの愚直実装を思いつきましたが,これは結構気に入っています。

E は解説できそうですが,まだ解けてないので割愛します。
F は問題を見てすらいません。

精進するぞい!!