蓝桥杯第十六届模拟赛第二期题解C++

十六届蓝桥杯模拟赛第二期

1.

【问题描述】

如果一个数 p 是个质数,同时又是整数 a 的约数,则 p 称为 a 的一个质因数。

请问, 2024 的最大的质因数是多少?

【答案提交】

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

答案为23

#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

bool isPrime(int n) // 素数判断
{
    if (n <= 1)
        return false;
    if (n == 2)
        return true;
    for (int i = 2; i <= sqrt(n); i++)
    {
        if (n % i == 0)
        {
            return false;
        }
    }
    return true;
}

int main()
{
    IOS;
    int n = 2024;
    int res = 0;
    for (int i = 2; i < n; i++)
    {
        if (isPrime(i))
        {
            if (n % i == 0) // 约数判断
            {
                res = max(res, i); // 取最大的约数
            }
        }
    }
    cout << res << endl;
    return 0;
}
2.

【问题描述】

对于两个整数 a, b,既是 a 的整数倍又是 b 的整数倍的数称为 a 和 b 的公倍数。公倍数中最小的正整数称为 a 和 b 的最小公倍数。

请问, 2024 和 1024 的最小公倍数是多少?

【答案提交】

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

答案为259072

#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int main()
{
    IOS;
    int a = 2024;
    int b = 1024;
    int len = a * b; // 确定范围
    int res = 1e8;
    for (int i = 1; i < len; i++) // 枚举
    {
        if (i % a == 0 && i % b == 0) // 判断
        {
            res = min(res, i); // 更新答案
        }
    }
    cout << res << endl;
    return 0;
}
3.

【问题描述】

两个数按位异或是指将这两个数转换成二进制后,最低位与最低位异或作为结果的最低位,次低位与次低位异或作为结果的次低位,以此类推。

例如,3 与 5 按位异或值为 6 。

请问,有多少个不超过 2024 的正整数,与 2024 异或后结果小于 2024 。

【答案提交】

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

答案为2001

#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int main()
{
    IOS;
    int n = 2024;
    int res = 0;
    for (int i = 1; i <= n; i++) // 枚举i
    {
        if ((i ^ n) < n) // 异或判断
        {
            res++; // 统计答案
        }
    }
    cout << res << endl;
    return 0;
}
4.

【问题描述】

小蓝有一个整数,初始值为 1 ,他可以花费一些代价对这个整数进行变换。

  • 小蓝可以花费 1 的代价将整数增加 1 。
  • 小蓝可以花费 3 的代价将整数增加一个值,这个值是整数的数位中最大的那个(1 到 9)。
  • 小蓝可以花费 10 的代价将整数变为原来的 2 倍。

例如,如果整数为 16,花费 3 将整数变为 22 。

又如,如果整数为 22,花费 1 将整数变为 23 。

又如,如果整数为 23,花费 10 将整数变为 46 。

请问,如果要将整数从初始值 1 变为 2024,请问最少需要多少代价?

【答案提交】

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

答案为79

#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
const int N = 1e9;
int max_(int x)
{
    int maxx = 0;
    while (x > 0)
    {
        int g = x % 10;
        if (g > maxx)
        {
            maxx = g;
        }
        x /= 10;
    }
    return maxx;
}
int main()
{
    IOS;
    int n = 2024;
    int dp[2030];
    for (int i = 0; i < 2030; i++) // 初始化
    {
        dp[i] = N;
    }
    dp[1] = 0; // 1的代价为0
    for (int i = 1; i <= n; i++)
    {
        if (i + 1 <= n) // 代价为1
        {
            dp[i + 1] = min(dp[i + 1], dp[i] + 1);
        }
        int maxx = max_(i); // 代价为3
        if (i + maxx <= n)
        {
            dp[i + maxx] = min(dp[i + maxx], dp[i] + 3);
        }
        if (i * 2 <= n) // 代价为10
        {
            dp[i * 2] = min(dp[i * 2], dp[i] + 10);
        }
    }
    cout << dp[n] << endl;
    return 0;
}
5.

【问题描述】

小蓝有以下 100 个整数:

534, 386, 319, 692, 169, 338, 521, 713, 640, 692, 969, 362, 311, 349, 308, 357, 515, 140, 591, 216,

57, 252, 575, 630, 95, 274, 328, 614, 18, 605, 17, 980, 166, 112, 997, 37, 584, 64, 442, 495,

821, 459, 453, 597, 187, 734, 827, 950, 679, 78, 769, 661, 452, 983, 356, 217, 394, 342, 697, 878,

475, 250, 468, 33, 966, 742, 436, 343, 255, 944, 588, 734, 540, 508, 779, 881, 153, 928, 764, 703,

459, 840, 949, 500, 648, 163, 547, 780, 749, 132, 546, 199, 701, 448, 265, 263, 87, 45, 828, 634.

小蓝想从中选出一部分数求和,使得和是 24 的倍数,请问这个和最大是多少?

【答案提交】

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

答案为49176

#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int a[] = {534, 386, 319, 692, 169, 338, 521, 713, 640, 692, 969, 362, 311, 349, 308, 357, 515, 140, 591, 216, 57, 252, 575, 630, 95, 274, 328, 614, 18, 605, 17, 980, 166, 112, 997, 37, 584, 64, 442, 495, 821, 459, 453, 597, 187, 734, 827, 950, 679, 78, 769, 661, 452, 983, 356, 217, 394, 342, 697, 878, 475, 250, 468, 33, 966, 742, 436, 343, 255, 944, 588, 734, 540, 508, 779, 881, 153, 928, 764, 703, 459, 840, 949, 500, 648, 163, 547, 780, 749, 132, 546, 199, 701, 448, 265, 263, 87, 45, 828, 634};
const int p = 24;
const int n = 100;
int main()
{
    IOS;
    int dp[25];
    memset(dp, -1, sizeof(dp));
    dp[0] = 0;
    for (int i = 0; i < n; i++) // 反向DP
    {
        int tmp = a[i];
        int new_dp[25];
        memcpy(new_dp, dp, sizeof(dp)); // 复制dp数组
        for (int j = 0; j < p; j++)
        {
            if (dp[j] != -1)
            {
                int k = (j + tmp) % p;                   // 计算新的余数
                new_dp[k] = max(dp[j] + tmp, new_dp[k]); // 更新最大和
            }
        }
        memcpy(dp, new_dp, sizeof(dp)); // 更新dp数组
    }
    cout << dp[0] << endl;
    return 0;
}
6.
【问题描述】

小蓝准备请自己的朋友吃饭。小蓝朋友很多,最终吃饭的人总数达 2024 人(包括他自己)。

请问如果每桌最多坐 n 人,最少要多少桌才能保证每个人都能吃饭。

【输入格式】

输入一行包含一个整数 n 。

【输出格式】

输出一行包含一个整数,表示最少的桌数。

【样例输入】

10

【样例输出】

203

【样例输入】

8

【样例输出】

253

【评测用例规模与约定】

对于所有评测用例,1 <= n <= 2024。

#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int main()
{
    IOS;
    int n;
    cin >> n;
    for (int i = 1; i <= 2024; i++) // n为1时,显然i为2024
    {
        if (i * n < 2024)
        {
            continue;
        }
        else
        {
            cout << i << endl;
            break;
        }
    }
    return 0;
}
7.

【问题描述】

小蓝有一个数组 a[1], a[2], …, a[n] ,请求出数组中值最小的偶数,输出这个值。

【输入格式】

输入的第一行包含一个整数 n 。

第二行包含 n 个整数,相邻数之间使用一个空格分隔,依次表示 a[1], a[2], …, a[n] 。

【输出格式】

输出一行,包含一个整数,表示答案。数据保证数组中至少有一个偶数。

【样例输入】

9
9 9 8 2 4 4 3 5 3

【样例输出】

2

【样例输入】

5

4321 2143 1324 1243 4312

【样例输出】

1324

【评测用例规模与约定】

对于 30% 的评测用例,1 <= n <= 100,0 <= a[i] <= 1000。

对于 60% 的评测用例,1 <= n <= 1000,0 <= a[i] <= 1000。

对于所有评测用例,1 <= n <= 10000,0 <= a[i] <= 1000000。

#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int main()
{
    IOS;
    int a[10005];
    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
    }
    sort(a, a + n); // 排序,默认从小到大
    for (int i = 0; i < n; i++)
    {
        if (a[i] % 2 == 0)
        {
            cout << a[i] << endl;
            break;
        }
    }
    return 0;
}
8.

【问题描述】

一个字符串包含LANQIAO是指在字符串中能取出几个字符,将他们按照在原串中的位置顺序摆成一排后字符串为 LANQIAO 。即字符串包含 LANQIAO 是指 LANQIAO 是这个串的子序列。

例如:LLLLLANHAHAHAQLANIIIIALANO 中包含 LANQIAO 。

又如:OAIQNAL 中不包含 LANQIAO 。

给点一个字符串,判断字符串中是否包含 LANQIAO 。

【输入格式】

输入一行包含一个字符串。

【输出格式】

如果包含 LANQIAO ,输出一个英文单词 YES ,否则输出一个英文单词 NO 。

【样例输入】

LLLLLANHAHAHAQLANIIIIALANO

【样例输出】

YES

【样例输入】

OAIQNAL

【样例输出】

NO

【评测用例规模与约定】

对于所有评测用例,输入的字符串非空串,由大写字母组成,长度不超过 1000 。

#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int main()
{
    IOS;
    string s;
    cin >> s;             // 目标串
    string t = "LANQIAO"; // 模式串
    int len_s = s.size();
    int len_t = t.size();
    int i = 0, j = 0;
    while (i < len_s && j < len_t) // 双指针
    {
        if (s[i] == t[j])
        {
            j++;
        }
        i++;
    }
    if (j == len_t) // 匹配成功
    {
        cout << "YES" << endl;
    }
    else
    {
        cout << "NO" << endl;
    }
    return 0;
}
9.

【问题描述】

小蓝有一个 n 行 m 列的矩阵 a[i][j] ,他想在矩阵中找出一个“口”字形状的区域,使得区域上的值的和最大。

具体讲,一个“口”字形状的区域可以由两个坐标 (x1, y1) 和 (x2, y2) 确定,满足:

  • 1 <= x1 < x2 <= n ;
  • 1 <= y1 < y2 <= m ;
  • x2 - x1 = y2 - y1 。

对应的区域由满足以下条件之一的点 (x, y) 构成:

  • x1 <= x <= x2,且 y = y1 ,对应“口”的左边一竖;
  • y1 <= y <= y2,且 x = x1 ,对应“口”的上面一横;
  • x1 <= x <= x2,且 y = y2 ,对应“口”的右边一竖;
  • y1 <= y <= y2,且 x = x2 ,对应“口”的下面一横。

请注意有些点满足以上条件的多个,例如左上角的点 (x1, y1) ,在计算时算为一个点。

区域上的值是指对应区域的所有点的值,即“口”字的框上的值,不含框内和框外的值。

【输入格式】

输入的第一行包含两个整数 n, m ,分别表示行数和列数。

接下来 n 行,每行包含 m 个整数,相邻数之间使用一个空格分隔,依次表示矩阵的每行每列的值,本部分的第 i 行第 j 列表示 a[i][j] 。

【输出格式】

输出一行包含一个整数,表示最大的和。

【样例输入】

5 6
1 -1 2 -2 3 -3
-1 2 -2 3 -3 4
2 -2 3 -3 4 -4
-2 3 -3 4 -4 5
3 -3 4 -4 5 -5

【样例输出】

4

【样例说明】

取 (x1, y1) = (1, 1) , (x2, y2) = (5, 5) 可得到最大值。

【评测用例规模与约定】

对于 30% 的评测用例,1 <= n, m <= 30 ,-1000 <= a[i][j] <= 1000 。

对于 60% 的评测用例,1 <= n, m <= 100 ,-1000 <= a[i][j] <= 1000 。

对于所有评测用例,1 <= n, m <= 300 ,-1000 <= a[i][j] <= 1000 。

解一:暴力
O ( n ) = O ( n ∗ m ∗ m i n ( n , m ) 2 ) O(n) = O(n * m * min(n, m)^2) O(n)=O(nmmin(n,m)2)

#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
const int N = 305;
int mp[N][N];
int n, m;
int res = 0;
// 求子矩阵的边界和
int get_edge(int x1, int y1, int x2, int y2)
{
    int sum = 0;
    // 左竖边(x1,y1)到(x2,y2)的边界和
    for (int i = x1; i <= x2; i++)
    {
        sum += mp[i][y1];
    }
    // 上横边(x1,y1)到(x2,y2)的边界和
    for (int i = y1; i <= y2; i++)
    {
        sum += mp[x1][i];
    }
    // 右竖边(x1,y1)到(x2,y2)的边界和
    for (int i = x1; i <= x2; i++)
    {
        sum += mp[i][y2];
    }
    // 下横边(x1,y1)到(x2,y2)的边界和
    for (int i = y1; i <= y2; i++)
    {
        sum += mp[x2][i];
    }
    sum -= (mp[x1][y1] + mp[x1][y2] + mp[x2][y1] + mp[x2][y2]); // 减去重复的边界
    return sum;
}
int main()
{
    IOS;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            cin >> mp[i][j];
        }
    }
    // 枚举子矩阵
    for (int x1 = 1; x1 <= n; x1++)
    {
        for (int y1 = 1; y1 <= m; y1++) 
        {// 从(x1,y1)到(x2,y2)的子矩阵
            for (int size = 1; x1 + size - 1 <= n && y1 + size - 1 <= m; size++) // 确保子矩阵为方阵
            {
                int x2 = x1 + size - 1;
                int y2 = y1 + size - 1;
                int sum = get_edge(x1, y1, x2, y2); // 子矩阵的边界和
                res = max(res, sum);                // 取最小值
            }
        }
    }
    cout << res << endl;
    return 0;
}

解二:前缀和优化
O ( n ) = O ( n ∗ m ∗ m i n ( n , m ) ) O(n) = O(n * m * min(n, m)) O(n)=O(nmmin(n,m))

#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
const int N = 305;
int mp[N][N];
int n, m;
int res = 0;
int prefix[N][N];
void prefix_init() // 前缀和初始化
{
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            prefix[i][j] = mp[i][j];
            if (i > 1)
            {
                prefix[i][j] += prefix[i - 1][j];
            }
            if (j > 1)
            {
                prefix[i][j] += prefix[i][j - 1];
            }
            if (i > 1 && j > 1)
            {
                prefix[i][j] -= prefix[i - 1][j - 1];
            }
        }
    }
}
int get_sum(int x1, int y1, int x2, int y2) // 求子矩阵的和
{
    int res = prefix[x2][y2];
    if (x1 > 1)
    {
        res -= prefix[x1 - 1][y2];
    }
    if (y1 > 1)
    {
        res -= prefix[x2][y1 - 1];
    }
    if (x1 > 1 && y1 > 1)
    {
        res += prefix[x1 - 1][y1 - 1];
    }
    return res;
}
// 求子矩阵的边界和
int get_edge(int x1, int y1, int x2, int y2)
{
    int sum = 0;
    // 左竖边(x1,y1)到(x2,y1)的边界和
    sum += get_sum(x1, y1, x2, y1);
    // 右竖边(x1,y2)到(x2,y2)的边界和
    sum += get_sum(x1, y2, x2, y2);
    // 上横边(x1,y1)到(x1,y2)的边界和
    sum += get_sum(x1, y1, x1, y2);
    // 下横边(x2,y1)到(x2,y2)的边界和
    sum += get_sum(x2, y1, x2, y2);
    sum -= (mp[x1][y1] + mp[x1][y2] + mp[x2][y1] + mp[x2][y2]); // 减去重复的边界
    return sum;
}
int main()
{
    IOS;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            cin >> mp[i][j];
        }
    }
    prefix_init(); // 前缀和初始化
    // 枚举子矩阵
    for (int x1 = 1; x1 <= n; x1++)
    {
        for (int y1 = 1; y1 <= m; y1++)
        {
            for (int size = 1; x1 + size - 1 <= n && y1 + size - 1 <= m; size++) // 确保子矩阵为方阵
            {
                int x2 = x1 + size - 1;
                int y2 = y1 + size - 1;
                int sum = get_edge(x1, y1, x2, y2); // 子矩阵的边界和
                res = max(res, sum);                // 取最小值
            }
        }
    }
    cout << res << endl;
    return 0;
}

上述前缀和使用容斥定理,高维前缀和可用下列代码优化

void highDimensionalPrefixSum(vector<vector<int>>& f, int n) {
	for (int j = 0; j < n; j++) {
		for (int i = 0; i < (1 << n); i++) {
			if (!(i >> j & 1)) {
				f[i] += f[i ^ (1 << j)];
			}
		}
	}
}
// 恢复原始值(根据高维前缀和结果反推)
void recoverOriginalValues(vector<vector<int>>& f, int n)
{
	for (int j = n - 1; j >= 0; j--) {
		for (int i = (1 << n) - 1; i >= 0; i--) {
			if (i >> j & 1) {
				f[i] -= f[i ^ (1 << j)];
			}
		}
	}
}

### 第16届蓝桥杯Java组模拟赛第二期题目及解答 #### 题目概述 针对第16届蓝桥杯Java组模拟赛第二期,提供了一套完整的题解方案[^2]。这些解决方案主要采用C++编写,但鉴于需求特别关注Java版本的解析。 #### 示例:质因数计数问题 考虑一道典型的填空题——求给定年份(如2024)的不同质因数的数量。此题目的核心在于遍历可能的除数并验证其是否为质数以及能否整除目标年份: ```java public class TM1 { public static void main(String[] args) { int count = 0; for (int i = 2; i < 2025 ; i++){ int flag = 1; if (2024 % i == 0){ for (int j = 2; j < i; j++){ if (i % j == 0){ flag = 0; break; } } if (flag == 1){ count++; } } } System.out.println("2024的质因数有:" + count + "个"); } } ``` 上述代码通过双重循环实现对指定范围内所有潜在因子的筛选,并最终输出符合条件的质因数量[^3]。 #### 平行四边形面积计算 另一类常见问题是几何图形的相关运算,比如基于输入长度和高度来计算平行四边形面积的问题。这类问题通常较为简单直接,只需按照基本公式`length * height`进行乘法操作即可得出结果: ```java import java.util.Scanner; public class T4 { public static void main(String[] args) { Scanner in = new Scanner(System.in); int length = in.nextInt(); int height = in.nextInt(); System.out.println(length * height); } } ``` 这段程序展示了如何读取用户输入的数据并通过简单的数学表达式完成所需的计算任务[^4]。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值