【ABC363】AtCoder Beginner Contest 363【C++】

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

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

### 開催日
2024/07/20 21:00-22:40

---

## [A: Piling Up](https://atcoder.jp/contests/abc363/tasks/abc363_a)
**解法**
- 問題文通り条件分岐する
- 計算して求める
    - $(\lfloor \frac{R}{100} \rfloor + 1) \times 100 - R$
```cpp:ABC363_1A.cpp
#include <iostream>
using namespace std;

int main(){
    int r;
    cin >> r;

    if(r<=99){
        cout << 99 - r + 1 << endl;
    }else if(r<=199){
        cout << 199 - r + 1 << endl;
    }else if(r<=299){
        cout << 299 - r + 1 << endl;
    }

    return 0;
}
```
```cpp:ABC363_2A.cpp
#include <iostream>
using namespace std;

int main(){
    int r;
    cin >> r;

    cout << (r / 100 + 1) * 100 - r << endl;
    return 0;
}
```

## [B: Japanese Cursed Doll](https://atcoder.jp/contests/abc363/tasks/abc363_b)
**解法**
- 問題文通りシミュレーションする
    - 毎回条件を満たしているか判定し、全員の髪の長さを $1$ 増やす
- $P$ 番目に髪が長い人の髪の長さが $T$ 以上になる日を求める
    - 髪の長さの降順にソートして $P$ 番目の人の髪の長さを取得する
```cpp:ABC363B_1.cpp
#include <iostream>
#include <vector>
using namespace std;

int main(){
    int n, t, p;
    cin >> n >> t >> p;

    vector<int> L(n);
    for(int i=0; i<n; i++){
        cin >> L[i];
    }

    int ans = 0;
    while(true){
        int cnt = 0;
        for(int i=0; i<n; i++){
            if(L[i]>=t){
                cnt++;
            }
        }

        if(cnt>=p){
            break;
        }

        ans++;

        for(int i=0; i<n; i++){
            L[i]++;
        }
    }

    cout << ans << endl;
    return 0;
}
```
```cpp:ABC363B_2.cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main(){
    int n, t, p;
    cin >> n >> t >> p;

    vector<int> L(n);
    for(int i=0; i<n; i++){
        cin >> L[i];
    }

    sort(L.rbegin(), L.rend());
    if(L[p-1]>=t){
        cout << 0 << endl;
    }else{
        cout << t - L[p-1] << endl;
    }

    return 0;
}
```

## [C: Avoid K Palindrome 2](https://atcoder.jp/contests/abc363/tasks/abc363_c)
**解法**
- 順列全探索
- 文字列 $S$ を昇順にソートしてから `next_permutation()` にかける
- 長さ $K$ の回文を部分文字列として含むかを全探索して判定する
```cpp:ABC363C.cpp
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

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

    string s;
    cin >> s;

    sort(s.begin(), s.end());

    int cnt = 0;
    do{
        bool flag = true;
        for(int i=0; i<=n-k; i++){
            string x = s.substr(i, k);
            string y = x;
            reverse(y.begin(), y.end());
            if(x==y){
                flag = false;
                break;
            }
        }

        if(flag){
            cnt++;
        }
    }while(next_permutation(s.begin(), s.end()));

    cout << cnt << endl;
    return 0;
}
```

## [D: Palindromic Number](https://atcoder.jp/contests/abc363/tasks/abc363_d)
**解法**
- 回文数の法則を考える
    - $d$ 桁の回文数を昇順に列挙すると、上位 $\lceil \frac{d}{2} \rceil$ 桁の昇順に並んでいる
    - 上位 $\lceil \frac{d}{2} \rceil$ 桁について考える
    - $d$ 桁の回文数は $9 \times 10^{\lfloor \frac{d - 1}{2} \rfloor}$ 個ある
    - $N$ 番目の回文数が何桁であるかを探して求める
- $1$ 桁の回文数に注意する
```cpp:ABC363D.cpp
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

int main(){
    long long int n;
    cin >> n;

    if(n<=10){
        cout << n - 1 << endl;
        return 0;
    }

    long long int cnt = 10;
    int keta;
    long long int x = 1, y, z;
    for(keta=2; ; keta++){
        if(n<=cnt){
            break;
        }

        if(keta%2==1){
            x *= 10;
        }

        z = x;
        
        y = x * 9;
        cnt += y;
    }
    
    n -= (cnt - y);
    string ans = to_string(z + n - 1);
    string rans;
    if(keta%2){
        rans = ans;
    }else{
        rans = ans.substr(0, ans.size()-1);
    }
    
    reverse(rans.begin(), rans.end());
    ans += rans;

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

## [E: Sinking Land](https://atcoder.jp/contests/abc363/tasks/abc363_e)
**解法**
- ダイクストラ法
- 初めて海に接した年 $x$ で場合分けする
    - $A_{i, j} > x$ ならば、 $A_{i, j}$ 年後に沈む
    - $A_{i, j} \leqq x$ ならば、 $x$ 年後に沈む
- 沈む年を `vector<vector<int>>` に記録する
- 沈む年と座標を `priority_queue<tuple<int, int, int>>` にプッシュする
- 最初から海に接している外周の区画で初期化する
- `map<int, int>` で各年に沈んだ区画数を記録する
```cpp:ABC363E.cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <tuple>
using namespace std;

int main(){
    int h, w, y;
    cin >> h >> w >> y;

    vector<vector<int>> G(h, vector<int>(w));
    for(int i=0; i<h; i++){
        for(int j=0; j<w; j++){
            cin >> G[i][j];
        }
    }

    vector<vector<int>> sink(h, vector<int>(w, -1));
    priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>, greater<tuple<int, int, int>>> Q;
    for(int i=0; i<h; i++){
        Q.emplace(G[i][0], i, 0);
        sink[i][0] = G[i][0];
        Q.emplace(G[i][w-1], i, w-1);
        sink[i][w-1] = G[i][w-1];
    }
    for(int i=0; i<w; i++){
        Q.emplace(G[0][i], 0, i);
        sink[0][i] = G[0][i];
        Q.emplace(G[h-1][i], h-1, i);
        sink[h-1][i] = G[h-1][i];
    }

    vector<int> dx = {0, 1, 0, -1}, dy = {1, 0, -1, 0};
    while(!Q.empty()){
        auto [height, x, y] = Q.top();
        Q.pop();

        if(sink[x][y]!=height){
            continue;
        }

        for(int i=0; i<4; i++){
            int nx = x + dx[i];
            int ny = y + dy[i];

            if(nx<0 || nx>h-1 || ny<0 || ny>w-1){
                continue;
            }
            if(sink[nx][ny]>0){
                continue;
            }
            
            int maxv = max(height, G[nx][ny]);
            sink[nx][ny] = maxv;
            Q.emplace(maxv, nx, ny);
        }
    }

    map<int, int> ans;
    for(int i=0; i<h; i++){
        for(int j=0; j<w; j++){
            ans[sink[i][j]]++;
        }
    }

    int cnt = h * w;
    for(int i=1; i<=y; i++){
        cout << cnt - ans[i] << endl;
        cnt -= ans[i];
    }

    return 0;
}
```