atcoderABC267场

A - SaturdayA - Saturday

Problem Statement
One day, tired from going to school, Takahashi wanted to know how many days there were until Saturday.
We know that the day was a weekday, and the name of the day of the week was SS in English.
How many days were there until the first Saturday after that day (including Saturday but not the starting day)?
Constraints
S is Monday, Tuesday, Wednesday, Thursday, or Friday.
在这里插入图片描述
在这里插入图片描述

题目大意

Takahashi想要知道距离周六还有多少天。已知当天是一个工作日,星期几用英文表示为SS。我们需要计算从当天开始到下一个周六(包括周六但不包括当天)的天数。

思路

(直接打印)首先读取输入的星期几S。然后,根据S的值确定距离下一个周六的天数。根据题目描述,星期一到星期五分别对应5、4、3、2、1天。最后,输出天数。

时间复杂度

O(1)

代码

#include<bits/stdc++.h>
using namespace std;
int main() {
    string S;
    cin >> S;
    int days = 0;
    if (S == "Monday") {
        days = 5;
    } else if (S == "Tuesday") {
        days = 4;
    } else if (S == "Wednesday") {
        days = 3;
    } else if (S == "Thursday") {
        days = 2;
    } else if (S == "Friday") {
        days = 1;
    }
    cout << days << endl;
    return 0;
}

B - Split? B

Problem Statement
Bowling pins are numbered 1 through 10. The following figure is a top view of the arrangement of the pins:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述Between the column containing a standing pin 5 and the column containing a standing pin 6 is a column containing Pins 3 and 9. Since Pins 3 and 9 are both knocked down, the placement is a split.

题目大意

根据题目描述,我们需要判断给定的保龄球排列是否为split。
split的定义是满足以下条件的情况:

  • 第一个球被击倒。
  • 存在两个不同的列满足以下条件:
    1.每个列都有一个或多个立着的球。
    2.存在一个列位于这两个列之间,该列中的所有球都被击倒。
    可以通过检查给定的排列是否满足这些条件来判断是否为split。

思路分析

(找两列有1的和一列在那两列中间且全是0的,共三列,三层循环)穷举搜索满足条件的每一对列,通过双重循环实现。为了检查是否存在一列中所有棋子都被击倒,在if块中添加第三个for语句。
但注意,一旦找到满足条件的一对列,我们可以输出Yes并终止执行。否则,可能会多次打印Yes。

新知识

s = ‘&’+s;
// prepend an arbitrary character to s
这行代码的作用是在字符串s的前面添加一个任意字符’&'。这样做的目的可能是为了在后续的代码中使用字符串s的下标索引时,将索引从1开始,而不是从0开始。这是一种常见的做法,特别是在一些算法或问题的实现中,为了方便处理边界情况或简化代码逻辑。

时间复杂度

O(1)

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    string s;
    cin >> s;
    s = '$' + s;
    if (s[1] == '1') {
        cout << "No\n";
    } else {
        array<bool, 7> column = {};
        column[0] = (s[7] == '1');
        column[1] = (s[4] == '1');
        column[2] = (s[2] == '1') or (s[8] == '1');
        column[3] = (s[1] == '1') or (s[5] == '1');
        column[4] = (s[3] == '1') or (s[9] == '1');
        column[5] = (s[6] == '1');
        column[6] = (s[10] == '1');
        for (int i = 0; i < 7; ++i) {
            for (int j = 0; j < i; ++j) {
                if (column[i] and column[j]) {
                    for (int k = j + 1; k < i; ++k) {
                        if (!column[k]) {
                            cout << "Yes\n";
                            return 0;
                        }
                    }
                }
            }
        }
        cout << "No\n";
    }
    return 0;
}

C - Index × A(Continuous ver.)

在这里插入图片描述在这里插入图片描述在这里插入图片描述

题目大意

给定一个长度为N的整数序列A和一个正整数M,要找出长度为M的连续子数组B,使得其对应位置的元素乘以索引的和最大。

思路分析

题目要求找出一个连续子数组B,使得按照索引位置乘以对应的值的和最大。我们可以遍历所有可能的连续子数组,计算每个子数组的和,然后取最大的和作为答案。但是这种穷举法时间复杂度为O(n2),会超过时间限制。所以我们可以使用前缀和数组来快速计算子数组的和,然后根据公式来计算每个连续子数组的乘积和。

技巧优化

利用前缀和和递推更新答案

时间复杂度

整体算法包括了从1到N的遍历,因此时间复杂度为O(N)

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main() {
    int n, m=0;
    ll ans=0;
    cin >> n >> m;
  vector<ll> a(n+1),sum(n+1);
  a[0]=0,sum[0]=0;
  
   // 循环读取 n 个数到数组 a,并计算前缀和存储在 sum 数组中
    for (int i = 1; i <=n; i++) {
        cin >> a[i];
        sum[i] = a[i] + sum[i - 1];
    }
    
    // 遍历前 m 个数,累加 i*ar[i] 到答案 ans 中
    for (int i = 1; i <= m; i++) {
        ans += i * a[i];
    }
    ll x =ans;
    for (int i = m + 1; i <= n; i++) {
      // 更新答案 ans,通过减去 sum[i-1]-sum[i-1-m] 并加上 m*a[i]
        ans -= sum[i - 1] - sum[i - 1 - m];
        ans += m * a[i];
        x = max(x, ans);
    }
    cout << x << endl;
    return 0;
}






  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值