【题解】AtCoder ABC365

T1

链接:CH, JP

按题意模拟即可。

#include <bits/stdc++.h>
using namespace std;
int y;
int main(){
    scanf("%d", &y);
    if(y % 4 != 0)
        printf("365\n");
    else if(y % 4 == 0 && y % 100 != 0)
        printf("366\n");
    else if(y % 100 == 0 && y % 400 != 0)
        printf("365\n");
    else if(y % 400 == 0)
        printf("366\n");
    return 0;
}

T2

链接:CH, JP

pair 存储数据和它的编号,从小到大排序之后输出倒数第二个数据的编号。
pair 的默认排序方法是按照 first 从小到大排序)

#include <bits/stdc++.h>
using namespace std;
const int N = 105;
int n;
pair<int, int> arr[N];
int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
        scanf("%d", &arr[i].first), arr[i].second = i;
    sort(arr + 1, arr + 1 + n);
    printf("%d\n", arr[n - 1].second);
    return 0;
}

T3

链接:CH, JP

如果 \(x\) 的值很大,最后的总花费应为 \(\sum a\),所以如果有 \(\sum a \leq m\),输出 infinite,结束程序。
对于剩下的情况,可以发现,对于 \(x' < x\),若 \(x\) 的补贴限额能使总花费不超过 \(m\)\(x'\) 也能做到;对于 \(x' > x\),若 \(x\) 会让总花费超过 \(m\)\(x'\) 也会。所以,本题的答案具有单调性:在一定范围内\(x\) 越大,总花费越大,反之则越小。
考虑用二分答案求解。令左端点 \(l = 0\),右端点 \(r = 2\times 10^{14} + 1\)(数据最大范围),对于一个 \(x\),验证它是否能让总花费不超过 \(m\)。若可以,将左端点移到 \(x\),若不可以,将右端点移到 \(x\)。最终 \(l + 1 = r\) 时,\(l\) 的值即为 \(x\) 的最大值。
注意:数据较大,要开 long long

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 2e5 + 5;
const ll inf = 2e14 + 1;
ll n, m, arr[N];
inline bool check(ll x){
    ll sum = 0;
    for(int i = 1; i <= n; i++)
        sum += min(x, arr[i]);
    return sum <= m;
}
int main(){
    scanf("%lld%lld", &n, &m);
    ll s = 0;
    for(int i = 1; i <= n; i++){
        scanf("%lld", &arr[i]);
        s += arr[i];
    }
    if(s <= m){
        printf("infinite\n");
        return 0;
    }
    ll l = 0, r = inf;
    while(l + 1 != r){
        ll mid = l + r >> 1;
        if(check(mid))
            l = mid;
        else
            r = mid;
    }
    printf("%lld\n", l);
    return 0;
}

T4

链接:CH, JP

\(f_{i, 0}\) 表示前 \(i\) 局高桥在不违反规则的情况下平局时,最多能胜多少场;
\(f_{i, 1}\) 表示前 \(i\) 局高桥在不违反规则的情况下获胜时,最多能胜多少场。
\(g(c) = \begin{cases}\text{'P'} & c = \text{'R'} \\ \text{'S'} & c = \text{'P'} \\ \text{'R'} & c = \text{'S'}\end{cases}\)(即对方出 \(c\) 时高桥的对策)
有:

\[f_{i, 0} = \max(\begin{cases} f_{i - 1, 0} & s_{i - 1} \neq s_{i} \\ f_{i - 1, 1} & g(s_{i - 1}) \neq s_{i}\\ \end{cases}) \]

\[f_{i, 1} = max(\begin{cases} f_{i - 1, 0} & s_{i - 1} \neq g(s_i) \\ f_{i - 1, 1} & g(s_{i - 1}) \neq g(s_i) \end{cases}) + 1 \]

注意初始化:\(f_{1, 0} = 0, f_{1, 1} = 1\)

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n, dp[N][2];
char s[N];
inline char get(char c){
    if(c == 'R')
        return 'P';
    else if(c == 'P')
        return 'S';
    else if(c == 'S')
        return 'R';
}
int main(){
    scanf("%d%s", &n, s + 1);
    dp[1][1] = 1, dp[1][0] = 0;
    for(int i = 2; i <= n; i++){
        char c1 = s[i - 1], c2 = get(s[i - 1]), c3 = s[i], c4 = get(s[i]);
        dp[i][0] = max((c1 != c3 ? dp[i - 1][0] : -1), (c2 != c3 ? dp[i - 1][1] : -1));
        // 由于 dp 数组中不会出现负数,所以取最大值时如果一个条件不成立,就会自动转成另一个值直接被赋值给 dp
        dp[i][1] = max((c1 != c4 ? dp[i - 1][0] : -1), (c2 != c4 ? dp[i - 1][1] : -1)) + 1;
    }
    printf("%d\n", max(dp[n][0], dp[n][1]));
    return 0;
}
posted @ 2025-02-12 10:20  Prülystic  阅读(16)  评论(0)    收藏  举报