【蓝桥杯】第十四届蓝桥杯省赛C/C++ B组

试题A:日期统计

【问题描述】

小蓝现在有一个长度为 100 的数组,数组中的每个元素的值都在 0 到 9 的范围之内。数组中的元素从左至右如下所示:
5 6 8 6 9 1 6 1 2 4 9 1 9 8 2 3 6 4 7 7 5 9 5 0 3 8 7 5 8 1 5 8 6 1 8 3 0 3 7 9 2 7 0 5 8 8 5 7 0 9 9 1 9 4 4 6 8 6 3 3 8 5 1 6 3 4 6 7 0 7 8 2 7 6 8 9 5 6 5 6 1 4 0 1 0 0 9 4 8 0 9 1 2 8 5 0 2 5 3 3
现在他想要从这个数组中寻找一些满足以下条件的子序列:

        1.子序列的长度为 8;
        2.这个子序列可以按照下标顺序组成一个 yyyymmdd 格式的日期,并且要求这个日期是 2023 年中的某一天的日期,例如 20230902,20231223。
        yyyy 表示年份,mm 表示月份,dd 表示天数,当月份或者天数的长度只有一位时需要一个前导零补充。
请你帮小蓝计算下按上述条件一共能找到多少个不同 的 2023 年的日期。
对于相同的日期你只需要统计一次即可。

【解题】

注意子序列的定义就好,子序列是序列的一部分,可以通过从原序列中删除一些(或不删除)元素但不改变其余元素的顺序得到。重点是顺序不变,以子序列的长度为条件,从头开始遍历数据。

(1)循环遍历,找到2023,i=0开始遍历,找到2,从此位置的下一个数开始遍历,找到0,依次类推,找到2和3

int find_2023(vector<int> arr){
    for(int i = 0 ; i < arr.size() - 7; i++)
    {
        if(arr[i] == 2){
            for(int j = i + 1;j < arr.size() - 6; j++){
                if(arr[j] == 0){
                    for(int k = j + 1; k < arr.size() - 5; k++){
                        if(arr[k] == 2){
                            for(int l = k + 1; l < arr.size() - 4; l++){
                                if(arr[l] == 3){
                                    return l + 1 ;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

2.month:存放月份的天数

month_checked:检查是否已经组合成功

mm:先找到第一个数小于2,在第二个变成十位数,如何是有效月份,就将month_checked记为1,

dd:先找到第一个数小于2,在第二个变成十位数,如何是有效日期,是就将子序列添加到vector

#include <iostream>
#include <vector>
#include <set>
using namespace std;

int find_2023(vector<int> arr){
    for(int i = 0 ; i < arr.size() - 7; i++)
    {
        if(arr[i] == 2){
            for(int j = i + 1;j < arr.size() - 6; j++){
                if(arr[j] == 0){
                    for(int k = j + 1; k < arr.size() - 5; k++){
                        if(arr[k] == 2){
                            for(int l = k + 1; l < arr.size() - 4; l++){
                                if(arr[l] == 3){
                                    return l + 1 ;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
int main() {
    vector<int> arr = {5, 6, 8, 6, 9, 1, 6, 1, 2, 4, 9, 1, 9, 8, 2, 3, 6, 4, 7, 7, 5, 9, 5, 0, 3, 8, 7, 5, 8, 1, 5, 8, 6, 1, 8, 3, 0, 3, 7, 9, 2,
                            7, 0, 5, 8, 8, 5, 7, 0, 9, 9, 1, 9, 4, 4, 6, 8, 6, 3, 3, 8, 5, 1, 6, 3, 4, 6, 7, 0, 7, 8, 2, 7, 6, 8, 9, 5, 6, 5, 6, 1, 4, 0, 1,
                            0, 0, 9, 4, 8, 0, 9, 1, 2, 8, 5, 0, 2, 5, 3, 3};
    vector<int> month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    vector<int> month_checked(12, 0);

    set<int> unique_set;

    for (int a = find_2023(arr); a < arr.size() - 3; a++) 
    {
        if (arr[a] < 2) 
        {
            for (int b = a + 1; b < arr.size() - 2; b++) 
            {
                int month1 = arr[a] * 10 + arr[b];
                if (0 < month1 && month1 < 13 && month_checked[month1 - 1] == 0) 
                {
                    month_checked[month1 - 1] = 1;
                    for (int c = b + 1; c < arr.size() - 1; c++) 
                    {
                        if (arr[c] < 4) 
                        {
                            for (int d = c + 1; d < arr.size(); d++) 
                            {
                                int day1 = arr[c] * 10 + arr[d];
                                if (0 < day1 && day1 <= month[month1 - 1]) 
                                {
                                    unique_set.insert(arr[a] * 1000 + arr[b] * 100 + arr[c] * 10 + arr[d]);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

   
    // 输出唯一日期的数量
    cout << unique_set.size() << endl;

    return 0;
}

set容器内部的元素唯一:

试题C:冶炼金属

【问题描述】

小蓝有一个神奇的炉子用于将普通金属 O 冶炼成为一种特殊金属 X。这个炉子有一个称作转换率的属性 V,V 是一个正整数,这意味着消耗 V 个普通金属 O 恰好可以冶炼出一个特殊金属 X,当普通金属 O 的数目不足 V 时,无法继续冶炼。
        现在给出了 N 条冶炼记录,每条记录中包含两个整数 A 和 B,这表示本次投入了 A 个普通金属 O,最终冶炼出了 B 个特殊金属 X。每条记录都是独立的,这意味着上一次没消耗完的普通金属 O 不会累加到下一次的冶炼当中。根据这 N 条冶炼记录,请你推测出转换率 V 的最小值和最大值分别可能是多少,题目保证评测数据不存在无解的情况。

【输入格式】

第一行一个整数 N,表示冶炼记录的数目。
接下来输入 N 行,每行两个整数 A、B,含义如题目所述。

【输出样式】

输出两个整数,分别表示 V 可能的最小值和最大值,中间用空格分开。

【样例输入】
3
75 3
53 2
59 2
【样例输出】
20 2

【解题】  

对一行冶炼记录来说,合成金属X,要么刚好消耗完 满足 等式 A/B=V,要么 剩余的金属O < V 即满足不等式 A - B*V < V => V > A / (B+1)

由不等式可知V_max是刚好消耗完的时候,V_min是刚好少一块金属O就能合成金属X,即不等式 A/B >= v > A/(B+1)

#include <iostream>
#include <climits>
using namespace std;

int main() {
    int n;
    int Vmin_max = 0;
    int Vmax_min = INT_MAX; // 使用<climits>中定义的最大int值
    int vmin, vmax;
    int a, b;
    
    cin >> n;
    for(int i = 0; i < n; i++){
        cin >> a >> b;

        vmax = a / b;
        vmin = a / (b + 1) + 1;
        if(vmax < Vmax_min){
            Vmax_min = vmax;
        }
        if (vmin > Vmin_max){
            Vmin_max = vmin;
        }
    }

    cout << Vmin_max << " " << Vmax_min << endl;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值