• AtCoder Beginner Contest 178


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

    A - not

    题意

    给出一个整数 $0 le x le 1$,如果 $x$ 是 $0$ 就输出 $1$,如果 $x$ 是 $1$ 就输出 $0$ 。

    题解

    输出 $x oplus 1$ 或 $!x$ 均可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int x;
        cin >> x;
        cout << (x ^ 1) << "
    ";
        return 0;
    }

    B - Product Max

    题意

    给出 $a,b,c,d$,问 $x imes y$ 的最大值。($-10^9 leq a leq x leq b leq 10^9$,$-10^9 leq c leq y leq d leq 10^9$)

    题解

    相似题目:CF1406B,枚举四个端点之积即可。

    简单解释一下:

    • 当 $x,y$ 均为正数或正端点之积较大,此时答案为 $b imes d$
    • 当 $x,y$ 均为负数或负端点之积较大,此时答案为 $a imes c$
    • 当 $x,y$ 一方为正数一方为负数,此时答案为 $a imes d$ 或 $b imes c$

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        long long a, b, c, d;
        cin >> a >> b >> c >> d;
        cout << max({a * c, a * d, b * c, b * d}) << "
    ";
        return 0;
    }

    C - Ubiquity

    题意

    找出满足以下条件的长为 $n$ 的不同序列的个数:

    • $0 le a_i le 9$
    • 序列中至少有一个 $a_i = 0$
    • 序列中至少有一个 $a_i = 9$

    答案对 $10^9+7$ 取模。

    题解

    总的序列个数为 $10^n$,

    不含 $0$ 的序列个数为 $9^n$,

    不含 $9$ 的序列个数为 $9^n$,

    不含 $0$ 和 $9$ 的序列个数为 $8^n$,

    根据容斥原理,答案即 $10^n - 2 imes 9^n + 8 ^ n$ 。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int MOD = 1e9 + 7;
    
    int binpow(int a, int b) {
        int res = 1;
        while (b) {
            if (b & 1) res = 1LL * res * a % MOD;
            a = 1LL * a * a % MOD;
            b >>= 1;
        }
        return res;
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n;
        cin >> n;
        cout << (0LL + binpow(10, n) - 2 * binpow(9, n) + binpow(8, n) + 2 * MOD) % MOD << "
    ";
        return 0;
    }

    D - Redistribution

    题意

    给出一个正整数 $s$,问有多少序列满足 $a_i ge 3$,且序列和为 $s$,答案对 $10^9+7$ 取模。

    题解一

    设 $dp_i$ 为序列和为 $i$ 的序列个数。

    初始时只有序列为空这一种情况,即 $dp_0 = 1$,之后每次向序列中添加大于等于 $3$ 的元素,最终答案即 $dp_s$ 。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    constexpr int MOD = 1e9 + 7;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int s;
        cin >> s;
        vector<int> dp(2020);
        dp[0] = 1;
        for (int i = 0; i <= s; i++) {
            for (int j = 3; i + j <= s; j++) {
                (dp[i + j] += dp[i]) %= MOD;
            }
        }
        cout << dp[s] << "
    ";
        return 0;
    }

    题解二

    $ dp_i = sumlimits_{j=0}^{i-3}dp_j $

    $ dp_{i-1} = sumlimits_{j=0}^{i-4}dp_j $

    $ dp_i = sumlimits_{j=0}^{i-3}dp_j = sumlimits_{j=0}^{i-4}dp_j + dp_{i-3} = dp_{i-1} + dp_{i - 3} $

    代码

    #include <bits/stdc++.h>
    using namespace std;
    constexpr int MOD = 1e9 + 7;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int s;
        cin >> s;
        vector<int> dp(2020);
        dp[0] = 1;
        for (int i = 3; i <= s; i++)
            dp[i] = (dp[i - 1] + dp[i - 3]) % MOD;
        cout << dp[s] << "
    ";
        return 0;
    }

    题解三

    已知序列和为 $s$ ,枚举序列的长度 $i$ 。

    因为每个元素都大于等于 $3$,假设每个元素都为 $3$ ,可以将多出来的 $ s-3*i$ 个 $1$ 看作 $n$ 个相同的小球放入 $m=i$ 个可为空的相同的盒子中。

    此时即转化为组合数学十二路问题中的 $ULA$ 问题,答案即 $sum_{i = 1}^{lfloor frac{s}{3} floor}C_{n+m - 1}^{m - 1}$ 。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    constexpr int N = 1e6 + 100;
    constexpr int MOD = 1e9 + 7;
    
    int fac[N], inv[N];
    
    int binpow(int a, int b) {
        int res = 1;
        while (b) {
            if (b & 1) res = 1LL * res * a % MOD;
            a = 1LL * a * a % MOD;
            b >>= 1;
        }
        return res;
    }
    
    int C(int n, int m){
        if(m < 0 or m > n) return 0;
        return 1LL * fac[n] * inv[m] % MOD * inv[n - m] % MOD;
    }
    
    void Init(){
        fac[0] = 1;
        for (int i = 1; i < N; i++) fac[i] = 1LL * fac[i - 1] * i % MOD;
        inv[N - 1] = binpow(fac[N - 1], MOD - 2);
        for (int i = N - 2; i >= 0; i--) inv[i] = 1LL * inv[i + 1] * (i + 1) % MOD;
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        Init();
        int s; 
        cin >> s;
        long long ans = 0;
        for (int i = 1; i <= s / 3; i++) {
            (ans += C(s - 3 * i + i - 1, i - 1)) %= MOD;
        }
        cout << ans << "
    ";
        return 0;
    }

    E - Dist Max

    题意

    给出 $n$ 个二维平面中的点,问两点间的最远曼哈顿距离。

    题解

    $(x_i,y_i), (x_j, y_j)$ 间的曼哈顿距离为 $|x_i-x_j| + |y_i-y_j|$ 。

    假设 $x_i ge x_j$,那么两点间的距离可能有两种情况:

    • $(x_i-x_j) + (y_i-y_j)$,移项得:$(x_i+y_i) - (x_j+ y_j)$
    • $(x_i-x_j) + (y_j-y_i)$,移项得:$(x_i-y_i) - (x_j- y_j)$

    所以对于每个点的坐标 $(x,y)$,分别用两个数组存储 $x+y$ 和 $x-y$,然后取两个数组较大的最值差即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n;
        cin >> n;
        vector<int> a(n), b(n);
        for (int i = 0; i < n; i++) {
            int x, y;
            cin >> x >> y;
            a[i] = x + y;
            b[i] = x - y;
        }
        sort(a.begin(), a.end());
        sort(b.begin(), b.end());
        cout << max(a.back() - a.front(), b.back() - b.front()) << "
    ";
        return 0;
    }

    F - Contrast

    题意

    给出两个非递减序列 $a$ 和 $b$,问能否重排 $b$ 使得 $a_i e b_i $ 。

    题解

    将序列 $b$ 反转,因为 $a$ 为非递减序,$b$ 为非递增序,所以序列中至多存在一段区间 $[l,r]$ 使得 $a_i = b_i = c$ 。

    如果区间外的某个 $b_j$ 与区间内的 $b_i$ 调换后满足题意,那么 $a_j e b_i, b_j e a_i$,即 $a_j e c$ 且 $b_j e c$ 。

    如果这样的 $b_j$ 个数小于区间长度则无解,否则输出调换后的序列 $b$ 即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n;
        cin >> n;
        vector<int> a(n), b(n);
        for (int i = 0; i < n; i++)
            cin >> a[i];
        for (int i = 0; i < n; i++)
            cin >> b[i];
        reverse(b.begin(), b.end());
        int c = -1;
        for (int i = 0; i < n; i++) {
            if (a[i] == b[i]) {
                c = a[i];
                break;
            }
        }
        int l = n, r = -1;
        for (int i = 0; i < n; i++) {
            if (a[i] == c and b[i] == c) {
                l = min(l, i);
                r = max(r, i);
            }
        }
        for (int i = 0; i < n; i++) {
            if (a[i] != c and b[i] != c and l <= r) {
                swap(b[i], b[l]);
                ++l;
            }
        }
        if (l <= r) {
            cout << "No" << "
    ";
            return 0;
        }
        cout << "Yes" << "
    ";
        for (int i = 0; i < n; i++) {
            cout << b[i] << " 
    "[i == n - 1];
        }
        return 0;
    }
  • 相关阅读:
    cin 与 getline
    ubuntu换源
    unbuntu 安装 bochs
    np.random.randint()的返回值
    vs2019 写入访问权限冲突
    44.Android之Shape设置虚线、圆角和渐变学习
    43.Android之ListView中BaseAdapter学习
    42.Android之ListView中ArrayAdapter简单学习
    Java编程思想学习(十六) 并发编程
    Java编程思想学习(十五) 注解
  • 原文地址:https://www.cnblogs.com/Kanoon/p/13666288.html
Copyright © 2020-2023  润新知