• 【ATcoder】AtCoder Beginner Contest 162 题解


    A - Lucky 7

    大水题,模拟即可。

    #include <iostream>
    #include <cstdio>
    using namespace std;
    int main() {
        string s;
        cin >> s;
        if (s[0] == '7' || s[1] == '7' || s[2] == '7') {
            puts("Yes");
        } else {
            puts("No");
        }
        return 0;
    }

    B - FizzBuzz Sum

    还是大水题,模拟。

    #include <iostream>
    #include <cstdio>
    using namespace std;
    int main() {
        int n;
        long long ans = 0;
        cin >> n;
        for (int i = 1; i <= n; i++) {
            if (i % 3 != 0 && i % 5 != 0) {
                ans += i;
            }
        }
        cout << ans;
        return 0;
    }

    C - Sum of gcd of Tuples (Easy)

    这次的前几题怎么都那么水鸭。

    数据范围那么小,暴力枚举即可。

    #include <iostream>
    #include <cstdio>
    using namespace std;
    int k;
    long long ans;
    int gcd(int a, int b) {
        if (b == 0) return a;
        return gcd(b, a % b);
    }
    int main() {
        cin >> k;
        for (int a = 1; a <= k; a++) {
            for (int b = 1; b <= k; b++) {
                int d = gcd(a, b), e;
                for (int c = 1; c <= k; c++) {
                    e = gcd(d, c);
                    ans += e;
                }
            }
        }
        cout << ans;
        return 0;
    }

    D - RGB Triplets

    枚举前两个数的位置,假设是i,j($i < j$)

    处理一个后缀颜色数量cnt[x][c]代表从x-n有多少颜色c。

    枚举的时候先加上cnt[j+1][除了i,j的另外一种颜色]

    然后再判断和i到j等距的那个点有没有被算上,如果被算上了直接减一即可。

    #include <iostream>
    #include <cstdio>
    using namespace std;
    long long n;
    char s[4010];
    long long cnt[4010][3];//0:R 1:G 2:B
    long long ans;
    long long f(char c) {
        if (c == 'R') return 0;
        if (c == 'G') return 1;
        return 2;
    }
    long long g(char a, char b) {
        return (3 - f(a) - f(b)) % 3;
    }
    int main() {
        scanf("%lld%s", &n, s + 1);
        for (long long i = n; i >= 1; i--) {
            cnt[i][0] = cnt[i + 1][0];
            cnt[i][1] = cnt[i + 1][1];
            cnt[i][2] = cnt[i + 1][2];
            cnt[i][f(s[i])]++;
        }
        for (long long i = 1; i < n - 1; i++) {
            for (long long j = i + 1; j < n; j++) {
                if (s[i] == s[j]) continue;
                ans += cnt[j + 1][g(s[i], s[j])];
                if (j + j - i <= n && f(s[j + j - i]) == g(s[i], s[j])) ans--;
            }
        }
        cout << ans;
        return 0;
    }

    E - Sum of gcd of Tuples (Hard)

    简单容斥。

    设dp[d]=gcd(a1,a2...an)=d的数列的数量,显然ai得是d的倍数,有$frac{k}{d}$种选择,所以有${frac{k}{d}}^n$个数列。

    但是这样会包含gcd=d*2,gcd=d*3...的答案,所以要减去。

    实现的时候倒着循环即可。

    #include <iostream>
    #include <cstdio>
    using namespace std;
    const long long mod = 1e9 + 7;
    long long n, k;
    long long dp[100010], ans;
    long long ksm(long long a, long long b) {
        long long ret = 1;
        while (b) {
            if (b & 1) {
                ret = (ret * a) % mod;
            }
            a = (a * a) % mod;
            b >>= 1;
        }
        return ret;
    }
    int main() {
        cin >> n >> k;
        for (long long i = k; i >= 1; i--) {
            long long num = k / i;
            dp[i] = ksm(num, n);
            for (long long j = i + i; j <= k; j += i) {
                dp[i] = (dp[i] - dp[j] + mod) % mod;
            }
            ans = (ans + dp[i] * i) % mod;
        }
        cout << ans;
        return 0;
    }

     F - Select Half

    动态规划。

    设计子状态dp[i]代表前i个数取$frac{i}{2}$个数的最大值,显然dp[1]=0。

    考虑转移方程。

    若i为奇数

    则若不选i,答案是dp[i-1],若选i,答案是dp[i-2]+a[i],在两者之间取max即可

    若i为偶数,若选i同上,若不选i只有取i-1以内左右编号为奇数的数这一种情况,两者取max即可。

    #include <iostream>
    #include <cstdio>
    using namespace std;
    long long n;
    long long a[200010];
    long long dp[200010];
    long long sum[200010];
    int main() {
        scanf("%lld", &n);
        for (long long i = 1; i <= n; i++) scanf("%lld", &a[i]);
        sum[1] = a[1];
        for (long long i = 3; i <= n; i += 2) {
            sum[i] = sum[i - 2] + a[i];
        }
        for (long long i = 2; i <= n; i++) {
            if (i & 1) {
                dp[i] = max(dp[i - 1], dp[i - 2] + a[i]);
            } else {
                dp[i] = max(sum[i - 1], dp[i - 2] + a[i]);
            }
        }
        printf("%lld", dp[n]);
        return 0;
    }
  • 相关阅读:
    erlang开发环境(IDE)搭建
    Mono for android,Xamarin点击事件的多种写法
    .NET C#中处理Url中文编码问题
    第一天正式学习,定一个学习目标吧。
    想转行做开发了!
    Java JMS 程序基础 与 ActiveMQ 安装(一)
    JDBC 基础
    Linux 6.4 设置yum 为centOS源
    C++ 简单实现 依赖注入(IOC)
    安卓项目
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/12717719.html
Copyright © 2020-2023  润新知