0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【ABC365】AtCoder Beginner Contest 365【C++】

Posted at

コンテスト名

トヨタ自動車プログラミングコンテスト2024#8(AtCoder Beginner Contest 365)

コンテストURL

開催日

2024/08/03 21:00-22:40


A: Leap Year

解法

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

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

    if(y%4!=0){
        cout << 365 << endl;
    }else if(y%100!=0){
        cout << 366 << endl;
    }else if(y%400!=0){
        cout << 365 << endl;
    }else{
        cout << 366 << endl;
    }

    return 0;
}

B: Second Best

解法

  • vector<pair<int, int>> で要素の値と位置を記録する
  • 降順にソートして 2 番目に大きい要素を取得する
ABC365B.cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

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

    vector<pair<int, int>> A;
    int a;
    for(int i=0; i<n; i++){
        cin >> a;
        A.emplace_back(a, i+1);
    }

    sort(A.rbegin(), A.rend());
    auto [value, num] = A[1];
    cout << num << endl;
    return 0;
}

C: Transportation Expenses

解法

  1. 累積和を利用して仮の上限額を求める
    • 交通費の配列 $A$ を昇順にソートして累積和を求める
    • 仮の上限額 $x'$ を $A_i$ のなかから選ぶ
    • 交通費が仮の上限額 $x'$ 以下の人 $i$ には $A_i$ 円が支給されるため、累積和を利用して合計を求める
    • 交通費が仮の上限額 $x'$ より大きい人には $x'$ 円が支給されるため、(交通費が仮の上限額 $x'$ より大きい人の人数 $\times \ x'$ )を求める
    • $M$ 円からこれらの総和を引いた残りの分を交通費が仮の上限額 $x'$ より大きい人に分配する
    • $A$ の最大値を $x$ にしたときでも交通費補助額の総和が $M$ 円以下になるならば、答えは無限になる
    • $A$ の最小値を仮の上限額 $x'$ にしたときでも条件を満たせない場合は、 $\lfloor \frac{M}{N} \rfloor$ が答えである
    • 計算量は $O(N \log N)$
  2. 答えを二分探索で求める
    • 交通費の配列 $A$ を昇順にソートして答えを二分探索で求める
    • 計算量は $O(N \log (\text{max}A))$
ABC365C_1.cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

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

    vector<long long int> A(n), S(n);
    for(int i=0; i<n; i++){
        cin >> A[i];
        S[i] = A[i];
    }

    sort(A.begin(), A.end());
    sort(S.begin(), S.end());

    for(int i=1; i<n; i++){
        S[i] += S[i-1];
    }

    for(int i=n-1; i>=0; i--){
        long long int sum = S[i];
        sum += A[i] * (n - 1 - i);

        if(sum<=m){
            if(A[i]==A[n-1]){
                cout << "infinite" << endl;
            }else{
                cout << A[i] + (m - sum)/(n - 1 - i) << endl;
            }
            return 0;
        }
    }

    cout << m / n << endl;
    return 0;
}
ABC365C_2.cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

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

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

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

    int low = 0, high = A.back() + 1;
    while(high-low>1){
        int mid = low + (high - low)/2;

        long long int sum = 0;
        for(int i=0; i<n; i++){
            sum += min(mid, A[i]);
        }

        if(sum<=m){
            low = mid;
        }else{
            high = mid;
        }
    }

    if(low>=A.back()){
        cout << "infinite" << endl;
    }else{
        cout << low << endl;
    }

    return 0;
}

D: AtCoder Janken 3

解法

  • 動的計画法 (DP)
  • $\text{dp}[i][j]$ := $i$ 回目に手 $j$ を出すときの勝った回数の最大値
  • $\text{R} = 0, \text{P} = 1, \text{S} = 2$ とすると、 $i - 1$ 回目の結果から求められる
    • 相手が $i$ 回目に $\text{R} = 0$ を出したとき
      • あいこ: $\text{dp}[i][0] = \text{max}(\text{dp}[i-1][1], \text{dp}[i-1][2])$
      • 勝ち: $\text{dp}[i][1] = \text{max}(\text{dp}[i-1][0], \text{dp}[i-1][2]) + 1$
ABC365D.cpp
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

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

    string s;
    cin >> s;

    vector<vector<int>> dp(n+1, vector<int>(3));
    for(int i=0; i<n; i++){
        if(s[i]=='R'){
            dp[i+1][0] = max(dp[i][1], dp[i][2]);
            dp[i+1][1] = max(dp[i][0], dp[i][2]) + 1;
        }else if(s[i]=='P'){
            dp[i+1][1] = max(dp[i][0], dp[i][2]);
            dp[i+1][2] = max(dp[i][0], dp[i][1]) + 1;
        }else if(s[i]=='S'){
            dp[i+1][2] = max(dp[i][0], dp[i][1]);
            dp[i+1][0] = max(dp[i][1], dp[i][2]) + 1;
        }
    }

    int ans = 0;
    for(int i=0; i<3; i++){
        ans = max(ans, dp[n][i]);
    }

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?