C++蓝桥杯真题(题目+解析+流程图)(特殊运算符+四叶玫瑰数+质因数的个数+最大的矩形纸片+数字游戏+活动人数)

C++蓝桥杯真题

    • 蓝桥杯省赛C++题目分析
      • 1. 特殊运算符
        • 题目描述
        • 输入描述
        • 输出描述
        • 输入输出样例
        • 正确代码
        • 错误代码
        • 分析
        • 流程图
      • 2. 四叶玫瑰数
        • 题目描述
        • 输入描述
        • 输出描述
        • 输入输出样例
        • 正确代码
        • 错误代码
        • 分析
        • 流程图
      • 3. 质因数的个数
        • 题目描述
        • 输入描述
        • 输出描述
        • 输入输出样例
        • 正确代码
        • 错误代码
        • 分析
        • 流程图
      • 4. 最大的矩形纸片
        • 题目描述
        • 输入描述
        • 输出描述
        • 输入输出样例
        • 正确代码
        • 错误代码
        • 分析
        • 流程图
      • 5. 数字游戏
        • 题目描述
        • 输入描述
        • 输出描述
        • 输入输出样例
        • 正确代码
        • 错误代码
        • 分析
        • 流程图
      • 6. 活动人数
        • 题目描述
        • 输入描述
        • 输出描述
        • 输入输出样例
        • 正确代码
        • 错误代码
        • 分析
        • 流程图

蓝桥杯省赛C++题目分析

1. 特殊运算符

题目描述

假定有一个运算符“>>>”,它的功能是取一个三位数的前两位。给定一个正整数N(100>>N)的结果。

输入描述

输入一个正整数N(100

输出描述

输出一个整数,表示N-(>>>N)的结果。

输入输出样例
  • 输入:257
  • 输出:232
正确代码
#include 
using namespace std;

int main() {
    int n;
    cin >> n;
    int k = n / 10; // “>>>”的意义指取一个三位数的前两位
    cout << n - k;
    return 0;
}
错误代码
#include 
using namespace std;

int main() {
    int n;
    cin >> n;
    int k = n / 100; // 错误地取了百位数
    cout << n - k;
    return 0;
}
分析

本题的关键在于理解“>>>”运算符的含义,即取三位数的前两位。通过整数除法n/10可以实现这一功能,而不是错误地使用n/100

流程图
开始
输入正整数N
计算k = n / 10
计算结果n - k
输出结果
结束

2. 四叶玫瑰数

题目描述

四叶玫瑰数是指一个四位数,其各位上的数字的四次方之和等于本身。给定两个正整数N和M,请将N~M(1≤N≤M≤1000000)之间(含N和M)的四叶玫瑰数按从小到大的顺序输出。

输入描述

第一行输入两个正整数N、M(1≤N≤M≤1000000)。

输出描述

输出一行,包含若干个用一个空格隔开的正整数,表示N~M之间的四叶玫瑰数。

输入输出样例
  • 输入:1234 2345
  • 输出:1634
正确代码
#include 
#include 
using namespace std;

bool isFourLeafRose(int num) {
    int a = num / 1000;
    int b = num / 100 % 10;
    int c = num / 10 % 10;
    int d = num % 10;
    return pow(a, 4) + pow(b, 4) + pow(c, 4) + pow(d, 4) == num;
}

int main() {
    int n, m;
    cin >> n >> m;
    for (int i = max(n, 1000); i <= min(m, 9999); i++) {
        if (isFourLeafRose(i)) {
            cout << i << " ";
        }
    }
    return 0;
}
错误代码
#include 
#include 
using namespace std;

bool isFourLeafRose(int num) {
    int a = num / 1000;
    int b = num / 100 % 10;
    int c = num / 10 % 10;
    int d = num % 10;
    return pow(a, 3) + pow(b, 3) + pow(c, 3) + pow(d, 3) == num; // 错误地使用了三次方
}

int main() {
    int n, m;
    cin >> n >> m;
    for (int i = n; i <= m; i++) {
        if (isFourLeafRose(i)) {
            cout << i << " ";
        }
    }
    return 0;
}
分析

本题需要判断一个四位数是否为四叶玫瑰数,即其各位数字的四次方之和是否等于该数本身。正确代码中使用了pow函数计算四次方,并通过循环遍历指定范围内的所有四位数来寻找符合条件的数。错误代码中错误地使用了三次方,导致无法正确判断四叶玫瑰数。

流程图
开始
输入N和M
遍历N到M
是否是四位数
判断是否为四叶玫瑰数
输出该数
继续下一个数
结束

3. 质因数的个数

题目描述

给定两个正整数N和M(1≤N≤M≤10000000),统计N到M之间(含N和M)每个数所包含的质因数的个数,输出其中最大的个数。

输入描述

输入两个正整数N和M(1≤N≤M≤10000000),两个正整数之间用一个空格隔开。

输出描述

输出一个整数,表示质因数个数中的最大值。

输入输出样例
  • 输入:6 10
  • 输出:3
正确代码
#include 
#include 
using namespace std;

vector<int> primeFactors(int num) {
    vector<int> factors;
    for (int i = 2; i * i <= num; i++) {
        while (num % i == 0) {
            factors.push_back(i);
            num /= i;
        }
    }
    if (num > 1) {
        factors.push_back(num);
    }
    return factors;
}

int main() {
    int n, m;
    cin >> n >> m;
    int maxCount = 0;
    for (int i = n; i <= m; i++) {
        vector<int> factors = primeFactors(i);
        int count = factors.size();
        maxCount = max(maxCount, count);
    }
    cout << maxCount;
    return 0;
}
错误代码
#include 
#include 
using namespace std;

vector<int> primeFactors(int num) {
    vector<int> factors;
    for (int i = 2; i <= num; i++) {
        if (num % i == 0) {
            factors.push_back(i);
        }
    }
    return factors;
}

int main() {
    int n, m;
    cin >> n >> m;
    int maxCount = 0;
    for (int i = n; i <= m; i++) {
        vector<int> factors = primeFactors(i);
        int count = factors.size();
        maxCount = max(maxCount, count);
    }
    cout << maxCount;
    return 0;
}
分析

本题需要统计每个数的质因数个数,并找出其中的最大值。正确代码中通过primeFactors函数分解质因数,使用vector存储质因数,并统计其数量。错误代码中错误地将所有因数都当作质因数,导致结果不准确。

流程图
开始
输入N和M
遍历N到M
分解质因数
统计质因数个数
更新最大值
是否遍历结束
输出最大值
结束

4. 最大的矩形纸片

题目描述

一张半边参差不齐的网格纸(网格边长均为1),有一边是完整没有破损的。现要从中剪出一片面积最大的矩形纸片。给定网格纸中完整边的长度N(1≤N≤1000000),以及网格中每一列残存部分的高度(1≤高度≤10000),输出能够剪出的最大矩形纸片面积。

输入描述

第一行输入一个正整数N(1≤N≤1000000),表示纸片完整边的长度。第二行输入N个正整数(1≤正整数≤10000),表示每列格子残存部分的高度,两个正整数之间用一个空格隔开。

输出描述

输出一个正整数,表示能够剪出的最大矩形纸片面积。

输入输出样例
  • 输入:6
    3 2 1 4 5 2
  • 输出:8
正确代码
#include 
#include 
#include 
using namespace std;

int largestRectangleArea(vector<int>& heights) {
    stack<int> s;
    int maxArea = 0;
    for (int i = 0; i <= heights.size(); i++) {
        int h = (i == heights.size()) ? 0 : heights[i];
        while (!s.empty() && h < heights[s.top()]) {
            int height = heights[s.top()];
            s.pop();
            int width = s.empty() ? i : i - s.top() - 1;
            maxArea = max(maxArea, height * width);
        }
        s.push(i);
    }
    return maxArea;
}

int main() {
    int n;
    cin >> n;
    vector<int> heights(n);
    for (int i = 0; i < n; i++) {
        cin >> heights[i];
    }
    cout << largestRectangleArea(heights);
    return 0;
}
错误代码
#include 
#include 
using namespace std;

int largestRectangleArea(vector<int>& heights) {
    int maxArea = 0;
    for (int i = 0; i < heights.size(); i++) {
        int minH = heights[i];
        for (int j = i; j < heights.size(); j++) {
            minH = min(minH, heights[j]);
            maxArea = max(maxArea, minH * (j - i + 1));
        }
    }
    return maxArea;
}

int main() {
    int n;
    cin >> n;
    vector<int> heights(n);
    for (int i = 0; i < n; i++) {
        cin >> heights[i];
    }
    cout << largestRectangleArea(heights);
    return 0;
}
分析

本题需要计算最大矩形面积。正确代码使用了单调栈的方法,通过维护一个单调递增栈来高效计算最大矩形面积。错误代码使用了暴力方法,时间复杂度较高,容易超时。

流程图
开始
输入N和高度数组
初始化栈和最大面积
遍历高度数组
栈不为空且当前高度小于栈顶高度
计算矩形面积
更新最大面积
弹出栈顶元素
将当前索引压入栈
是否遍历结束
输出最大面积
结束

5. 数字游戏

题目描述

老师给出了一组数,要求小蓝对这组数进行调整,调整的规则如下:

  1. 第1次,从这组数中选出一个最小的数,把它调整为和第二小的数一样大;
  2. 第2次,再从这组数中选出一个最大的数,把它调整为和第二大的数一样大;
  3. 重复执行1、2步骤;
  4. 当这组数中所包含的不同的数少于3个时,结束调整。
    现在给定了一组数,请帮小蓝编写程序计算出总共的调整次数,以及调整结束时这组数中的最小数和最大数。
输入描述

第一行输入一个正整数N(3≤N≤1000000),表示这组数中数的个数。第二行输入N个正整数(1≤正整数≤1000000),正整数之间用一个空格隔开。

输出描述

输出一行,包含三个整数,分别是总的调整次数、调整结束时的最小值和最大值,整数之间用一个空格隔开。

输入输出样例
  • 输入:4
    1 3 4 2
  • 输出:2 2 3
正确代码
#include 
#include 
#include 
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> nums(n);
    for (int i = 0; i < n; i++) {
        cin >> nums[i];
    }
    sort(nums.begin(), nums.end());
    int count = 0;
    while (unique(nums.begin(), nums.end()) - nums.begin() >= 3) {
        nums[0] = nums[1];
        nums.back() = nums[nums.size() - 2];
        sort(nums.begin(), nums.end());
        count++;
    }
    cout << count << " " << nums[0] << " " << nums.back();
    return 0;
}
错误代码
#include 
#include 
#include 
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> nums(n);
    for (int i = 0; i < n; i++) {
        cin >> nums[i];
    }
    sort(nums.begin(), nums.end());
    int count = 0;
    while (unique(nums.begin(), nums.end()) - nums.begin() >= 3) {
        nums[0] = nums[1];
        nums.back() = nums[nums.size() - 2];
        count++;
    }
    cout << count << " " << nums[0] << " " << nums.back();
    return 0;
}
分析

本题需要按照规则调整数组,直到数组中不同元素的个数少于3个。正确代码中通过排序和unique函数来判断不同元素的个数,并在每次调整后重新排序。错误代码中没有重新排序,导致调整后的数组顺序错误,无法正确判断不同元素的个数。

流程图
flowchart TD
    A[开始] --> B[输入N和数组]
    B --> C[排序数组]
    C --> D{不同元素个数是否小于3}
    D -- 是 --> E[输出调整次数、最小值、最大值]
    D -- 否 --> F[调整最小值]
    F --> G[调整最大值]
    G --> H[重新排序]
    H --> D
    E --> I[结束]

6. 活动人数

题目描述

有一个大型企业集团,由N个部门组成,编号从1到N。这些部门之间的层次关系形成了一个树状结构,一个上级部门可能会有1个或多个直接下级部门,一个下级部门只有一个直接上级部门。本月集团举办了一个大型活动,活动组织方要求:如果一个上级部门参加本次活动,那么他们的直接下级部门就不能参加,而他的间接下级部门可以参加。请你帮他们计算一下,如何安排可以使参加活动的人数最多,并输出参加活动的最多人数。

输入描述

第一行输入一个正整数N(1≤N≤100000),表示集团所有部门的数量。接下来有N行,每行输入三个非负整数F、S和C(0≤F≤N,1≤S≤N,F≠S,1≤C≤1000),F表示是部门S的直接上级,C表示部门S的人数,整数之间用一个空格隔开。注意:如果是最上层的部门,其直接上级部门编号为0。

输出描述

输出一个整数,表示参加活动的最多人数。

输入输出样例
  • 输入:6
    0 1 2
    1 2 4
    1 3 3
    2 4 3
    3 5 2
    3 6 4
  • 输出:11
正确代码
#include 
#include 
using namespace std;

const int MAXN = 100005;
vector<int> tree[MAXN];
int people[MAXN];
int dp[MAXN][2]; // dp[i][0]表示部门i不参加,dp[i][1]表示部门i参加

void dfs(int node, int parent) {
    dp[node][0] = 0;
    dp[node][1] = people[node];
    for (int child : tree[node]) {
        if (child == parent) continue;
        dfs(child, node);
        dp[node][0] += max(dp[child][0], dp[child][1]);
        dp[node][1] += dp[child][0];
    }
}

int main() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        int f, s, c;
        cin >> f >> s >> c;
        people[s] = c;
        if (f != 0) {
            tree[f].push_back(s);
            tree[s].push_back(f);
        }
    }
    dfs(1, 0);
    cout << max(dp[1][0], dp[1][1]);
    return 0;
}
错误代码
#include 
#include 
using namespace std;

const int MAXN = 100005;
vector<int> tree[MAXN];
int people[MAXN];
int dp[MAXN][2]; // dp[i][0]表示部门i不参加,dp[i][1]表示部门i参加

void dfs(int node, int parent) {
    dp[node][0] = 0;
    dp[node][1] = people[node];
    for (int child : tree[node]) {
        if (child == parent) continue;
        dfs(child, node);
        dp[node][0] += dp[child][1];
        dp[node][1] += dp[child][0];
    }
}

int main() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        int f, s, c;
        cin >> f >> s >> c;
        people[s] = c;
        if (f != 0) {
            tree[f].push_back(s);
            tree[s].push_back(f);
        }
    }
    dfs(1, 0);
    cout << max(dp[1][0], dp[1][1]);
    return 0;
}
分析

本题需要使用树形DP来解决。正确代码中通过DFS遍历树,并使用dp数组记录每个部门参加或不参加时的最大人数。错误代码中在更新dp数组时没有正确处理子节点的状态,导致结果不准确。

流程图
开始
输入N和部门信息
初始化树和人数数组
DFS遍历树
初始化dp数组
遍历子节点
子节点是否为父节点
跳过
递归处理子节点
更新dp数组
是否所有子节点处理完毕
返回
输出最大人数
结束

希望这些分析和代码对你有所帮助!如果有任何问题或需要进一步的解释,请随时告诉我。

你可能感兴趣的:(C++,c++,蓝桥杯)