湖南2024年 CSP-J 模拟赛详解

T1简单数学

题目描述

给定一个正整数 k k k,求最小的 x x x,使得 x x x 可以整除 k k k,且 x > n x>n x>n

n n n是另一个由输入给定的用于限定范围的整数。

输入格式

你的程序将输入两个整数,依次是 n n n k k k

输出格式

输出一个整数,表示 x x x

样例 #1

样例输入 #1

32 7

样例输出 #1

35

样例 #2

样例输入 #2

81 9

样例输出 #2

90

提示

0 ≤ n , k ≤ 2147483647 0≤n,k≤2147483647 0nk2147483647

这个问题可以通过简单的数学计算来解决。我们需要找到一个最小的正整数 x x x,它满足两个条件: x x x 可以整除 k k k x > n x > n x>n。由于 x x x 必须大于 n n n 并且能被 k k k 整除,我们可以通过将 k k k 乘以一个大于 n / k n / k n/k 的最小整数来找到 x x x

下面是用C++实现的代码示例:

#include <bits/stdc++.h>

using namespace std;

int main() {
    int n, k;
    cin >> n >> k;
    int x;
    if (n % k == 0)
    	x = n + k;
    else 
    	x = n + (k - n % k) % k;

    cout << x << endl;

    return 0;
}

T2阶乘之和

题目背景

我们定义阶乘: n ! = 1 × 2 × 3 × … … × n n!=1×2×3×……×n n!=1×2×3×……×n

特别的, 0 ! = 1 0!=1 0!=1

题目描述

对于任意指定的 n n n,我们定义阶乘之和为 s = 1 ! + 2 ! + 3 ! + … … + n ! s=1!+2!+3!+……+n! s=1!+2!+3!+……+n!

当然,因为是阶乘之和,运算结果会非常大。

比如当 n = 23 n=23 n=23 的时候, s = 27029669736328405580313 s=27029669736328405580313 s=27029669736328405580313

显然这超出了大家目前的处理能力,所以善良的出题人只需要大家输出 s s s 的后八位数即可。

当然输出不包括高位的 0 0 0,比如你发现后八位是 00123456 00123456 00123456,那你只需要输出 123456 123456 123456

输入格式

输入仅一个正整数,表示 n n n

输出格式

输出仅一个整数,表示 s s s 的后八位。

样例 #1

样例输入 #1

5

样例输出 #1

153

样例 #2

样例输入 #2

23

样例输出 #2

5580313

提示

n ≤ 100 , 000 n≤100,000 n100,000

这个问题可以通过使用一种称为“模运算”的数学技巧来解决,特别是当我们只对结果的最后几位感兴趣时。模运算允许我们通过在每一步计算中都对结果取模,从而避免处理非常大的数字。

在C++中,我们可以使用 % 运算符来执行模运算。由于我们只对最后八位数字感兴趣,我们可以在每次乘法和加法后都对结果取模 1 0 8 10^8 108

下面是用C++实现的代码示例:

#include <iostream>

using namespace std;

int main() {
    long long n, s = 0, f = 1;
    cin >> n;

    for (long long i = 1; i <= n; ++i) {
        f = f * i % 100000000; // 计算阶乘并取模
        s = (s + f) % 100000000; // 计算阶乘之和并取模
    }

    // 输出结果
    cout << s << endl;

    return 0;
}

T3石子合并

题目描述

现在有 n n n 堆石子排成一列,其中第 i i i 堆石子有 a i a_i ai 个。每次将两堆石子合并成一堆,新堆的石子数是原来两堆石子数之和,合并的代价是原来两堆石子数之积

求最终将 n n n 堆石子合并成一堆的代价和最小值是多少

输入格式

输入数据有两行,第一行一个正整数,表示 n n n

第二行 n n n 个正整数,以空格隔开,表示 a i a_i ai

输出格式

输出数据仅一行,一个整数,表示答案

样例 #1

样例输入 #1

2
2 2

样例输出 #1

4

样例 #2

样例输入 #2

4
2 3 7 5

样例输出 #2

101

提示

a 1 a_1 a1 a 2 a_2 a2 合并成新的一堆,石子数为 5 5 5,合并的代价为 6 6 6

然后这新的一堆与原来的 a 4 a_4 a4 合并成新的一堆,石子数是 10 10 10,合并的代价为 25 25 25

最后这新的一堆与 a 3 a_3 a3 合并,合并后的石子数为 17 17 17,合并的代价为 70 70 70,最后总的合并的最小代价为 6 + 25 + 70 = 101 6+25+70 = 101 62570=101

n ≤ 4 , 000 , 000 n ≤4,000,000 n4,000,000

这个问题可以通过贪心算法来解决。贪心算法的基本思想是在每一步选择中都采取在当前状态下最好或最优的选择,从而希望导致结果是全局最好或最优的算法。

对于这个问题,我们可以将石子堆按照石子的数量从小到大排序,然后从最小的两个堆开始合并,每次合并后更新合并后的堆的大小,并重新排序。重复这个过程,直到所有的石子堆合并成一堆。

下面是用C++实现的代码示例:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> piles(n);
    for (int i = 0; i < n; ++i) {
        cin >> piles[i];
    }

    // 将石子堆按照石子数量从小到大排序
    sort(piles.begin(), piles.end());

    // 初始化代价为0
    long long cost = 0;
    // 当还有多于一堆石子时继续合并
    while (piles.size() > 1) {
        // 取出最小的两个石子堆进行合并
        int first = piles.back(); piles.pop_back();
        int second = piles.back(); piles.pop_back();
        int merged = first + second;

        // 计算合并的代价
        cost += first * second;

        // 将合并后的石子堆加入到石子堆列表中,并保持列表有序
        piles.push_back(merged);
        sort(piles.begin(), piles.end());
    }

    // 输出最小合并代价
    cout << cost << endl;

    return 0;
}

这段代码首先读取输入的石子堆数量和每个石子堆的石子数,然后按照石子数对石子堆进行排序。接着,使用一个循环来不断地合并最小的两个石子堆,直到只剩下一个石子堆为止。在每次合并时,计算并累加合并的代价。最后,输出计算出的最小合并代价。

请注意,这个算法的时间复杂度主要取决于排序操作,最坏情况下为 O ( n 2 ∗ l o g n ) O(n^2 * log n) O(n2logn),因为每次合并后都需要重新排序。对于非常大的n值,可能需要更高效的算法来处理。

T4寿司转盘

题目描述

昨天,我和朋友们外出聚餐吃日料,发现了一个有趣的事实,许多盘寿司围成了一个圆圈,这些寿司中有红色的也有蓝色的。我想,通过一些操作,就可以使得所有的红色寿司形成了一块连续的区域,蓝色的寿司也形成了一块连续的区域。

如果每次只可以交换相邻的两盘寿司,那么最少需要多少步才可以达到要求呢?

输入格式

本题有多组数据。

输入数据第一行,一个正整数 T T T,表示数据组数。

接下来 T T T 行,每行一行由 B B B R R R 组成的字符串, B B B 表示蓝色, R R R 表示红色。第 i i i 个字符描述顺时针数第 i i i 盘寿司的颜色。注意,最后一盘寿司和第一盘寿司是相邻的。

输出格式

输出数据有 T T T 行,对于每组数据,输出一行,表示答案

样例 #1

样例输入 #1

1
BBRBBRBBBRRR

样例输出 #1

5

提示

交换位置 2 2 2、位置 3 3 3 上的寿司;

交换位置 1 1 1、位置 2 2 2 上的寿司;

交换位置 6 6 6、位置 7 7 7 上的寿司;

交换位置 7 7 7、位置 8 8 8 上的寿司;

交换位置 8 8 8、位置 9 9 9 上的寿司;

对于 20 20 20% 的数据, n ≤ 20 n≤20 n20

对于 50 50 50% 的数据, n ≤ 20 , 000 n≤20,000 n20,000

对于 100 100 100% 的数据, T ≤ 10 , n ≤ 1 , 000 , 000 T≤10,n≤1,000,000 T10n1,000,000

这个问题可以通过贪心算法来解决。我们的目标是将所有的红色寿司(记为 ′ R ′ 'R' R)移动到一起,所有的蓝色寿司(记为 ′ B ′ 'B' B)也移动到一起。由于每次只能交换相邻的两盘寿司,我们可以采取以下步骤:

  1. 找到第一个红色寿司的位置。
  2. 找到最后一个红色寿司的位置。
  3. 计算红色寿司区域外的蓝色寿司数量。
  4. 将红色寿司区域外的蓝色寿司数量除以 2 2 2,因为每次交换可以移动两个蓝色寿司。
  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值