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

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

    A - Multiplication 1

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        int a, b; cin >> a >> b;
        cout << a * b << "
    ";
    }

    B - Multiplication 2

    题意

    计算 $a_1 imes a_2 imes ... imes a_n$ 。($2≤n≤10^5, 0≤ a_i ≤ 10^{18}$) 

    题解一

    若 $ans$ 乘以某个 $a_i$ 大于 $10^{18}$ 则溢出,即:

    $ans imes a_i > 10^{18}$,

    为避免运算过程中乘积溢出,移项得:$a_i > frac{10^{18}}{ans}$ 。

    代码

    #include <bits/stdc++.h>
    using ll = long long;
    using namespace std;
    const ll MAXN = 1e18;
    int main() {
        int n; cin >> n;
        ll a[n] = {};
        for (int i = 0; i < n; i++)
            cin >> a[i];
        if (count(a, a + n, 0)) {
            cout << 0 << "
    ";
            return 0;
        }
        ll ans = 1;
        for (int i = 0; i < n; i++) {
            if (a[i] > MAXN / ans) {
                cout << -1 << "
    ";
                return 0;
            }
            ans *= a[i];
        }
        cout << ans << "
    ";
    }

    题解二

    转化为 __int128 可以避免溢出。

    代码

    #include <bits/stdc++.h>
    using ll = long long;
    using namespace std;
    const ll MAXN = 1e18;
    int main() {
        int n; cin >> n;
        ll a[n] = {};
        for (int i = 0; i < n; i++)
            cin >> a[i];
        if (count(a, a + n, 0)) {
            cout << 0 << "
    ";
            return 0;
        }
        ll ans = 1;
        for (int i = 0; i < n; i++) {
            if ((__int128)ans * a[i] > MAXN) {
                cout << -1 << "
    ";
                return 0;
            }
            ans *= a[i];
        }
        cout << ans << "
    ";
    }

    题解三

    如果能由下一个积除以 $a_i$ 得到现在的积说明不会发生溢出,但是这个方法需要用 $unsigned long long$ 才行。

    代码

    #include <bits/stdc++.h>
    using ull = unsigned long long;
    using namespace std;
    const ull MAXN = 1e18;
    int main() {
        int n; cin >> n;
        ull a[n] = {};
        for (int i = 0; i < n; i++)
            cin >> a[i];
        if (count(a, a + n, 0)) {
            cout << 0 << "
    ";
            return 0;
        }
        ull ans = 1;
        for (int i = 0; i < n; i++) {
            ull next = ans * a[i];
            if (next / a[i] != ans or next > MAXN) {
                cout << -1 << "
    ";
                return 0;
            }
            ans *= a[i];
        }
        cout << ans << "
    ";
    }

    题解四

    使用 python 中自带的大数运算。

    代码

    def main():
        N = int(input())
        A = list(map(int, input().split()))
    
        if 0 in A:
            print(0)
            return
    
        ans = 1
        for a in A:
            ans *= a
            if ans > int(1e18):
                print(-1)
                return
    
        print(ans)
    
    main()

    C - Multiplication 3

    题意

    $a$ 为整数,$b$ 为保留小数点后两位的小数,计算 $a imes b$ 。($0≤a≤10^{15}, 0≤ b < 10$) 

    题解

    把 $b$ 转化为整数再计算。

    代码

    #include <bits/stdc++.h>
    using ll = long long;
    using namespace std;
    int main() {
        ll a; string s; cin >> a >> s;
        s.erase(1, 1);
        ll b = stoll(s);
        cout << a * b / 100;
    }

    D - Div Game

    题意

    给出一个正整数 $n$,每次操作可以选择一个正整数 $z$,要求:

    • $z = p^e$,$p$ 为正素数,$e$ 为正数
    • $z$ 整除 $n$
    • $z$ 不同于任一之前选择的 $z$
    • 如果以上条件满足,$n = frac{n}{z}$

    找出最多可以进行多少次操作。

    题解

    找出每个质因数的个数,依次减去 $1,2,3...$ 即可。

    代码

    #include <bits/stdc++.h>
    using ll = long long;
    using namespace std;
    int main() {
        ll n; cin >> n;
        map<ll, ll> mp;
        for (ll i = 2; i * i <= n; i++) {
            while (n % i == 0) {
                ++mp[i];
                n /= i;
            }
        }
        if (n != 1) ++mp[n];
        ll ans = 0;
        for (auto i : mp) {
            for (int j = 1; j <= i.second; j++) {
                i.second -= j;
                ++ans;
            }
        }
        cout << ans << "
    ";
    }

    E - Count Median

    题意

    有 $n$ 个数 $x_1,x_2,...,x_n$,$a_i≤x_i≤b_i$,找出中值 $x_{mid}$ 可能的值的个数。

    • 中值为将所有 $x_i$ 排序,位于中间的 $x_i$
    • 如果 $n$ 为奇数,中值为 $x_{(n+1)/2}$
    • 如果 $n$ 为偶数,中值为 $(x_{n/2} + x_{n/2 + 1}) / 2$

    题解

    中值的最小值为 $a_i$ 的中值,最大值为 $b_i$ 的中值,中值的个数即:$b_{mid} - a_{mid} + 1$ 。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        int n; cin >> n;
        int a[n] = {}, b[n] = {};
        for (int i = 0; i < n; i++)
            cin >> a[i] >> b[i];
        sort(a, a + n);
        sort(b, b + n);
        int mi = 0, mx = 0;
        if (n & 1) {
            mi = a[n / 2];
            mx = b[n / 2];
        } else {
            mi = a[n / 2 - 1] + a[n / 2];
            mx = b[n / 2 - 1] + b[n / 2];
        }
        cout << mx - mi + 1;
    }

    F - Knapsack for All Subsets

    题意

    有 $n$ 个数 $a_1,a_2,...,a_n$,计算 ${1,2,...,n}$ 的 $2^n - 1$ 个非空子集有多少子集作为下标求和可以得到 $s$ 。

    题解

    $dp_i$ 表示和为 $i$ 的集合共有多少个。

    每次添加一个数 $x$,会产生两种变化:

    • $x$ 与 $dp_i$ 中的每个集合构成的新集合都可以构成 $i + x$:$dp_{i + x} += dp_i$
    • $x$ 与 $dp_i$ 中的每个集合构成了一个包含原先集合的新集合:$dp_i *= 2$

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int mod = 998244353;
    int dp[6010];
    int main() {
        int n, s; cin >> n >> s;
        dp[0] = 1;
        for (int i = 0; i < n; i++) {
            int x; cin >> x;
            for (int j = s; j >= 0; j--) {
                (dp[j + x] += dp[j]) %= mod;
                (dp[j] *= 2) %= mod;
            }
        }
        cout << dp[s] << "
    ";
    }
  • 相关阅读:
    C:大数相加
    杭电2186:悼念512汶川大地震遇难同胞——一定要记住我爱你
    实验五
    安装vmtools
    ubuntu20.04换源
    实验一 灯程序——OK6410A开发板LINUX3.0.1(嵌入式开发)
    OK6410A开发板LINUX3.0.1配置(嵌入式开发)
    实验四 Makefile
    虚拟机联网
    实验三 按键灯
  • 原文地址:https://www.cnblogs.com/Kanoon/p/13024678.html
Copyright © 2011-2022 走看看