• AtCoder Beginner Contest 267 (A~D)


    A. Saturday

    题意:

    告诉你今天星期几,问距离周六还有几天。

    思路:

    直接输出即可。

    代码如下:

    #include 
    #include 
    using namespace std;
    
    int main()
    {
        string s;
        cin >> s;
    
        if (s == "Monday") cout << 5 << endl;
        if (s == "Tuesday") cout << 4 << endl;
        if (s == "Wednesday") cout << 3 << endl;
        if (s == "Thursday") cout << 2 << endl;
        if (s == "Friday") cout << 1 << endl;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    B. Split?

    题意:

    有一个保龄球图,保龄球编号从 1 到 10,其分布如下图所示。

    将图中两条虚线的每个部分称为一列。
    在这里插入图片描述

    给定一个长度为 10 的 01串,一一对应每个保龄球,其中 0 表示被击倒,1 表示未被击倒。

    问给定的序列是否满足:

    • 第一个保龄球被击倒

    • 存在两列都有未被击倒的保龄球,并且中间存在一列,其中的保龄球全部被击倒。

    满足输出 Yes ,不满足则输出 No .

    思路:

    先将字符转化为数字存放在 a[] 中,再进行判断:要满足题意,那么 1 号必须为 0 .

    接下来逐个分析,要求至少有一列都为 0 ,且除了该列之外每一列都至少有一个 1 .

    代码如下:

    #include 
    #include 
    #include 
    #define ll long long 
    using namespace std;
    
    int main()
    {
        string s;
        cin >> s;
        s = ' ' + s;
    
        int a[20];
        for (int i = 1; i <= 10; i++)
            a[i] = s[i] - '0';
    
        if (s[1] == '0'){
            int sum = 0;
            for (int i = 1; i <= 10; i++){
                sum += a[i];
            }
            if (sum == 0){
                cout << "No" << endl;
                return 0;
            }
    
            if (a[3] + a[9] == 0){
                cout << "Yes" << endl;
                return 0;
            }
            if (a[2] + a[8] == 0){
                cout << "Yes" << endl;
                return 0;
            }
            if (a[5] == 0){
                cout << "Yes" << endl;
                return 0;
            }
            if (a[7] == 1 && a[4] == 0){
                cout << "Yes" << endl;
                return 0;
            }
            if (a[10] == 1 && a[6] == 0){
                cout << "Yes" << endl;
                return 0;
            }
    
            cout << "No" << endl;
        }
        else puts("No");
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    C. Index × A (Continuous ver.)

    题意:

    给定一个长度为 n 的数组 A,要求找到一段长度为 m 的连续子序列 B,使得 B 中每个数与其序号的乘积之和最大,输出最大值。

    思路:

    很容易想到用双指针来做,维护一个长度为 m 的滑动窗口,每次移动,都是将后一个数加入并将第一个数移出,还要重新计算当前窗口内的数值,如果每次都这样操作一遍的话,很容易时间复杂度过高导致超时。

    我们发现每次移动前面都减少了一个从 lr 的区间和,由此想到可以用一个前缀和数组来维护区间和。

    代码如下:

    #include 
    #include 
    #include 
    #define ll long long 
    using namespace std;
    const int N = 2e5 + 10;
    
    ll a[N];
    ll s[N];
    
    int main()
    {
        int n, m;
        cin >> n >> m;
    
        for (int i = 1; i <= n; i++){
            cin >> a[i];
            s[i] = s[i - 1] + a[i]; //前缀和
        }
    
        ll res = 0;
        for (int i = 1; i <= m; i++) //初始窗口,前m个数
            res += a[i] * i;
    
        //双指针
        ll ans = res;
        for (int i = m + 1; i <= n; i++){
            int l = i - m + 1, r = i;
            res += m * a[r] - (s[r - 1] - s[l - 2]);
            ans = max(ans, res);
        }
    
        cout << ans << endl;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    D.Index × A (Not Continuous ver.)

    题意:

    与上题类似,只不过将连续子序列改成了子序列(可以不连续)。

    给定一个长度为 n 的数组 A,要求找到一段长度为 m 的子序列 B,使得 B 中每个数与其序号的乘积之和最大,输出最大值。

    思路:

    n 的范围较大,考虑使用 dp 来做。

    定义 f[i][j] 表示前 i 个数中选了 j 个数。

    得到状态转移方程为:f[i][j] = max(f[i - 1][j - 1] + a[i] * j, f[i - 1][j]) .

    代码如下:

    #include 
    #include 
    #include 
    #define ll long long
    using namespace std;
    const int N = 2010;
    
    int a[N];
    ll f[N][N]; //表示前i个数选了j个数
    
    int main()
    {
        int n, m;
        cin >> n >> m;
    
        memset(f, -0x3f, sizeof(f));
        
        for (int i = 1; i <= n; i++){
            cin >> a[i];
            f[i][0] = 0;
        }
    
        f[0][0] = 0; //初始化
        for (int i = 1; i <= n; i++){
            for (int j = 1; j <= m && j <= i; j++){
                f[i][j] = max(f[i - 1][j - 1] + a[i] * j, f[i - 1][j]);
            }
        }
    
        cout << f[n][m] << endl;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

  • 相关阅读:
    35. 反转链表
    从零备战蓝桥杯——动态规划(递推篇)
    LeetCode-22. 括号生成-Java-medium
    Kubernetes(K8S)集群搭建基础入门教程
    DDD领域驱动设计
    [C++学习] 多进程通信共享内存
    【AI工程论文解读】03-DevOps for AI-人工智能应用开发面临的挑战
    星淘惠告诉你跨境平台那么多,凭什么要选亚马逊?
    推荐算法:HNSW算法简介
    Java二叉树(1)
  • 原文地址:https://blog.csdn.net/qq_59904473/article/details/126915562