zoukankan      html  css  js  c++  java
  • AtCoder Beginner Contest 179

    比赛链接:https://atcoder.jp/contests/abc179/tasks

    A - Plural Form

    题意

    给出一个由小写字母组成的单词,如果单词以 $s$ 结尾,在单词的末尾加上 $es$,否则在单词的末尾加上 $s$ 。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        string s;
        cin >> s;
        cout << s + (s.back() == 's' ? "es" : "s") << "
    ";
        return 0;
    }

    B - Go to Jail

    题意

    给出一对骰子投掷 $n$ 次的结果,问是否有连续三次两个骰子的点数相同。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n;
        cin >> n;
        vector<int> x(n), y(n);
        for (int i = 0; i < n; i++)
            cin >> x[i] >> y[i];
        for (int i = 0; i + 2 < n; i++) {
            if (x[i] == y[i] and x[i + 1] == y[i + 1] and x[i + 2] == y[i + 2]) {
                cout << "Yes" << "
    ";
                return 0;
            }
        }
        cout << "No" << "
    ";
        return 0;
    }

    C - A x B + C

    题意

    给出一个正整数 $n$,问有多少不同的三元组 $(a, b, c)$ 满足 $a,b,c > 0$ 且 $a imes b + c = n$ 。

    题解

    枚举 $a$ 的值,与之对应的 $b$ 的最大值为 $lfloor frac{n}{a} floor$,然后判断是否都能取到即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n;
        cin >> n;
        long long ans = 0;
        for (int a = 1; a <= n; a++) {
            ans += n / a - (n % a == 0);
        }
        cout << ans << "
    ";
        return 0;
    }

    D - Leaping Tak

    题意

    给出 $k$ 个区间,区间并集中的整数为每次可以选择行走的距离,问在数轴上从点 $1$ 走到点 $n$ 的路径数目。

    题解

    与上一场的D题类似,可以考虑如下代码:

    dp[1] = 1;
    for (int i = 1; i < n; i++) {
        for (int j = 0; j < k; j++) {
            for (int k = l[j]; k <= r[j]; k++) {
                (dp[i + k] += dp[i]) %= MOD;
            }
        }
    }

    但是 $O_{(n^2k)}$ 的复杂度明显会超时。

    注意到第三层循环为区间操作,所以可以考虑用差分或线段树降低复杂度。

    代码一

    差分,时间复杂度为 $O_{(nk)}$ 。

    #include <bits/stdc++.h>
    using namespace std;
    constexpr int MOD = 998244353;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n, k;
        cin >> n >> k;
        vector<int> l(k), r(k);
        for (int i = 0; i < k; i++)
            cin >> l[i] >> r[i];
        vector<long long> dp(2 * n + 100);
        dp[1] = 1;
        dp[2] = -1;
        for (int i = 1; i <= n; i++) {
            dp[i] += dp[i - 1];
            dp[i] = (dp[i] % MOD + MOD) % MOD;
            for (int j = 0; j < k; j++) {
                dp[i + l[j]] += dp[i];
                dp[i + r[j] + 1] -= dp[i];
            }
        }
        cout << dp[n] << "
    ";
        return 0;
    }

    代码二

    线段树,时间复杂度为 $O_{(nlog_nk)}$ 。

    #include <bits/stdc++.h>
    #define lson i << 1
    #define rson i << 1 | 1
    #define mid ((l + r) >> 1)
    using namespace std;
    constexpr int N = 2e5 + 100;
    constexpr int MOD = 998244353;
    long long sum[N << 2], lazy[N << 2];
    void build(int i, int l, int r) {
        if (l == r) {
            sum[i] = 0;
            return;
        }
        build(lson, l, mid);
        build(rson, mid + 1, r);
        sum[i] = sum[lson] + sum[rson];
    }
    void push_down_lazy(int i, int l, int r) {
        if (lazy[i] != 0) {
            (sum[lson] += lazy[i] * (mid - l + 1)) %= MOD;
            (sum[rson] += lazy[i] * (r - mid)) %= MOD;
            (lazy[lson] += lazy[i]) %= MOD;
            (lazy[rson] += lazy[i]) %= MOD;
            lazy[i] = 0;
        }
    }
    void update(int i, int l, int r, int L, int R, int val) {
        if (L <= l and r <= R) {
            (sum[i] += 1LL * val * (r - l + 1) % MOD) %= MOD;
            (lazy[i] += val) %= MOD;
            return;
        }
        push_down_lazy(i, l, r);
        if (L <= mid) update(lson, l, mid, L, R, val);
        if (R > mid) update(rson, mid + 1, r, L, R, val);
        sum[i] = (sum[lson] + sum[rson]) % MOD;
    }
    long long query(int i, int l, int r, int L, int R) {
        if (L <= l and r <= R) {
            return sum[i];
        }
        push_down_lazy(i, l, r);
        long long res = 0;
        if (L <= mid) res += query(lson, l, mid, L, R);
        if (R > mid) res += query(rson, mid + 1, r, L, R);
        return res % MOD;
    }
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n, k;
        cin >> n >> k;
        vector<int> l(k), r(k);
        for (int i = 0; i < k; i++)
            cin >> l[i] >> r[i];
        build(1, 1, n);
        update(1, 1, n, 1, 1, 1);
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < k; j++) {
                if (i + l[j] <= n) {
                    update(1, 1, n, i + l[j], min(n, i + r[j]), query(1, 1, n, i, i));
                }
            }
        }
        cout << query(1, 1, n, n, n) << "
    ";
        return 0;
    }

    E - Sequence Sum

    题意

    $a_1 = x, a_{n+1} = a_n^2 % m$,计算 $displaystyle{sum_{i=1}^n a_i}$ 。

    题解

    找出循环节的起点和终点即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        long long n, x, m;
        cin >> n >> x >> m;
        const int N = min(n + 1, m + 2);
        vector<int> a(N);
        vector<int> vis(m);
        a[1] = x;
        vis[x] = 1;
        long long ans = 0;
        for (int i = 2; i < N; i++) {
            a[i] = a[i - 1] * a[i - 1] % m;
            if (vis[a[i]]) {
                long long sum1 = accumulate(a.begin(), a.begin() + vis[a[i]], 0LL);
                vector<int> cycle;
                for (int j = vis[a[i]]; j < i; j++) {
                    cycle.push_back(a[j]);
                }
                n -= vis[a[i]] - 1;
                long long sum2 = accumulate(cycle.begin(), cycle.end(), 0LL);
                long long sum3 = accumulate(cycle.begin(), cycle.begin() + n % cycle.size(), 0LL);
                cout << sum1 + sum2 * (n / cycle.size()) + sum3 << "
    ";
                return 0;
            } else {
                vis[a[i]] = i;
            }
        }
        ans = accumulate(a.begin(), a.end(), 0LL);
        cout << ans << "
    ";
        return 0;
    }

    F - Simplified Reversi

    题意

    有一个 $n imes n$ 的棋盘,棋盘中间 $(n-2) imes (n-2)$ 的方阵中为黑子,棋盘的最右列和最下行为白子。

    接下来有 $q$ 次操作:

    • $(1, x)$:在棋盘的第一行的 $x$ 列放置一枚白子,白字与该列最近的白子之间均变为白子
    • $(2, x)$:在棋盘的第一列的 $x$ 行放置一枚白子,白字与该行最近的白子之间均变为白子

    问 $q$ 操作之后还有多少个黑子。

    题解

    更新最左列和最上行的同时存储移动过程中黑子个数固定的列和行。(也可以直接用二维线段树但我不会

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n, q;
        cin >> n >> q;
        long long ans = 1LL * (n - 2) * (n - 2);
        vector<int> row(n + 1), col(n + 1);
        int pos_row = n, pos_col = n;
        for (int i = 0; i < q; i++) {
            int op, pos;
            cin >> op >> pos;
            if (op == 1) {
                if (pos < pos_col) {
                    ans -= pos_row - 2;
                    while (pos_col > pos) col[pos_col--] = pos_row - 2;
                } else {
                    ans -= col[pos];
                }
            } else {
                if (pos < pos_row) {
                    ans -= pos_col - 2;
                    while (pos_row > pos) row[pos_row--] = pos_col - 2;
                } else {
                    ans -= row[pos];
                }
            }
        }
        cout << ans << "
    ";
        return 0;
    }
  • 相关阅读:
    MySQL-基本sql命令
    Java for LeetCode 203 Remove Linked List Elements
    Java for LeetCode 202 Happy Number
    Java for LeetCode 201 Bitwise AND of Numbers Range
    Java for LeetCode 200 Number of Islands
    Java for LeetCode 199 Binary Tree Right Side View
    Java for LeetCode 198 House Robber
    Java for LeetCode 191 Number of 1 Bits
    Java for LeetCode 190 Reverse Bits
    Java for LeetCode 189 Rotate Array
  • 原文地址:https://www.cnblogs.com/Kanoon/p/13702225.html
Copyright © 2011-2022 走看看