2024年天梯赛训练赛1-10题:题目题解与思想解析(C++简化版)

目录

7-1 什么是机器学习

7-2 考试周

7-3 谁是赢家

7-4 拯救外星人

7-5 吉老师的回归

7-6 倒数第N个字符串

7-7 出租

7-8 分寝室

7-9 彩虹瓶

7-10 简单计算器


7-1 什么是机器学习

题目:

什么是机器学习?上图展示了一段面试官与“机器学习程序”的对话:

面试官:9 + 10 等于多少?
答:3
面试官:差远了,是19。
答:16
面试官:错了,是19。
答:18
面试官:不,是19。
答:19

本题就请你模仿这个“机器学习程序”的行为。

输入格式:

输入在一行中给出两个整数,绝对值都不超过 100,中间用一个空格分开,分别表示面试官给出的两个数字 A 和 B。

输出格式:

要求你输出 4 行,每行一个数字。第 1 行比正确结果少 16,第 2 行少 3,第 3 行少 1,最后一行才输出 A+B 的正确结果。

题解:

1、简单的签到题直接cout输出

#include
using namespace std;
int main(){
    int a, b; cin >> a >> b;
    int n = a + b;
    cout << n - 16<< endl;
        cout <

7-2 考试周

题目:

考试周快到了,浙江大学的电子屏又调皮了…… 本题请你帮小编写一个自动倒计时的程序,对给定的日期(例如“腊八”就对应 8)和倒计时天数(例如电子屏上的“四天之后”就对应 4),自动调整公式里的分母(例如 8/2=4 里面的那个 2)。

输入格式:

输入在一行中给出两个正整数:A 是给定的日期,不超过 30;B 是倒计时天数,不超过 10。

输出格式:

在一行中输出公式 A/X=B,其中 X 是满足等式的数字,输出时保留小数点后 1 位即可。

题解:

1、第二题也是签到题,直接输出

#include
using namespace std;
int main(){
    int a, b; cin >> a >> b;
   double n;
    n = (double)a / b;
    printf("%d/%.1f=%d", a, n, b);
}

7-3 谁是赢家

题目:

某电视台的娱乐节目有个表演评审环节,每次安排两位艺人表演,他们的胜负由观众投票和 3 名评委投票两部分共同决定。规则为:如果一位艺人的观众票数高,且得到至少 1 名评委的认可,该艺人就胜出;或艺人的观众票数低,但得到全部评委的认可,也可以胜出。节目保证投票的观众人数为奇数,所以不存在平票的情况。本题就请你用程序判断谁是赢家。

输入格式:

输入第一行给出 2 个不超过 1000 的正整数 Pa 和 Pb,分别是艺人 a 和艺人 b 得到的观众票数。题目保证这两个数字不相等。随后第二行给出 3 名评委的投票结果。数字 0 代表投票给 a,数字 1 代表投票给 b,其间以一个空格分隔。

输出格式:

按以下格式输出赢家:

The winner is x: P1 + P2

其中 x 是代表赢家的字母,P1 是赢家得到的观众票数,P2 是赢家得到的评委票数。

题解:

1、题目主要考察‘条件判断’和‘简单逻辑推理。

2、创建数组st,分别用索引0和1表示a和b两个人,记录评委为其投票数量。

3、最后直接判断是否满足题目要求:谁大,有无评委投票。

#include
using namespace std;
int st[3];
int main(){
    int a, b; cin >> a >> b;
    int win, t;
    for(int i = 1; i <= 3; i ++)
    {
        cin >> t;
        st[t] ++;
    }
    if(a > b && st[0]) printf("The winner is a: %d + %d", a, st[0]);
    else if (st[0] == 3) printf("The winner is a: %d + %d", a, st[0]);
    else printf("The winner is b: %d + %d", b, st[1]);
}

7-4 拯救外星人

题目:

你的外星人朋友不认得地球上的加减乘除符号,但是会算阶乘 —— 正整数 N 的阶乘记为 “N!”,是从 1 到 N 的连乘积。所以当他不知道“5+7”等于多少时,如果你告诉他等于“12!”,他就写出了“479001600”这个答案。

本题就请你写程序模仿外星人的行为。

输入格式:

输入在一行中给出两个正整数 A 和 B。

输出格式:

在一行中输出 (A+B) 的阶乘。题目保证 (A+B) 的值小于 12。

题解:

1、考察数学知识,阶乘的概念。

2、首先将题目给的两个数字相加,为我们需要阶乘的n!。

3、采用while循环,从n开始阶乘,直到n为0跳出循环。

#include
using namespace std;
int main(){
   int a, b; cin >> a >> b;
    int n = a + b;
    int ans = 1;
    while(n)
    {
        ans *= n --;
    }
    cout <

7-5 吉老师的回归

题目:

曾经在天梯赛大杀四方的吉老师决定回归天梯赛赛场啦!

为了简化题目,我们不妨假设天梯赛的每道题目可以用一个不超过 500 的、只包括可打印符号的字符串描述出来,如:Problem A: Print "Hello world!"

众所周知,吉老师的竞赛水平非常高超,你可以认为他每道题目都会做(事实上也是……)。因此,吉老师会按照顺序看题并做题。但吉老师水平太高了,所以签到题他就懒得做了(浪费时间),具体来说,假如题目的字符串里有 qiandao 或者 easy(区分大小写)的话,吉老师看完题目就会跳过这道题目不做。

现在给定这次天梯赛总共有几道题目以及吉老师已经做完了几道题目,请你告诉大家吉老师现在正在做哪个题,或者吉老师已经把所有他打算做的题目做完了。

提醒:天梯赛有分数升级的规则,如果不做签到题可能导致团队总分不足以升级,一般的选手请千万不要学习吉老师的酷炫行为!

输入格式:

输入第一行是两个正整数 N,M (1≤M≤N≤30),表示本次天梯赛有 N 道题目,吉老师现在做完了 M 道。

接下来 N 行,每行是一个符合题目描述的字符串,表示天梯赛的题目内容。吉老师会按照给出的顺序看题——第一行就是吉老师看的第一道题,第二行就是第二道,以此类推。

输出格式:

在一行中输出吉老师当前正在做的题目对应的题面(即做完了 M 道题目后,吉老师正在做哪个题)。如果吉老师已经把所有他打算做的题目做完了,输出一行 Wo AK le

题解:

1、考察字符串知识,判断字符串是否存在。

2、遍历所有的输入的字符串,判断到不存在“easy”或者“qiandao”,就将该字符串保存到res中备用,并且用ans代表他需要做的题+1。

3、最后判断完成的题目是否比需要完成的题目多,是则AK,不是就找到现在正在做的题。

#include
using namespace std;
const int N = 40;
string s[N];
vector res;
int main(){
    int a, b;
    cin >> a >>b;
    int i = 1;
    int ans = 0;
    getline(cin, s[0]);
    for(i = 1; i <= a; i ++)
    {
        getline(cin, s[i]);
        if(s[i].find("easy") != -1 || s[i].find("qiandao") != -1)
            continue;
        else{
            res.push_back(s[i]);
            ans ++;
        }
    }
    if(ans <= b) cout << "Wo AK le";
    else {
        cout << res[b];
    }
}

7-6 倒数第N个字符串

题目:

给定一个完全由小写英文字母组成的字符串等差递增序列,该序列中的每个字符串的长度固定为 L,从 L 个 a 开始,以 1 为步长递增。例如当 L 为 3 时,序列为 { aaa, aab, aac, ..., aaz, aba, abb, ..., abz, ..., zzz }。这个序列的倒数第27个字符串就是 zyz。对于任意给定的 L,本题要求你给出对应序列倒数第 N 个字符串。

输入格式:

输入在一行中给出两个正整数 L(2 ≤ L ≤ 6)和 N(≤105)。

输出格式:

在一行中输出对应序列倒数第 N 个字符串。题目保证这个字符串是存在的。

题解:

1、这道题题意可以看出,是想考察进制转换,顺便查找数组。

2、26个字母当然就是26进制咯,用maxx来保存n位数的大小。

3、仔细想想,倒数第一个,用数字表示就是maxx,那么倒数第二个就是maxx - 1,所以倒数第res个就是maxx - res + 1。

4、通过while对n进行回滚遍历,依次输出每个字符,结果就是我们需要的字符串了

#include
using namespace std;
const int N = 26;
int main(){
    int n, res; cin >> n >> res;
    int maxx = 0;
    for(int i = 0; i < n; i ++)
        maxx += (int)pow(N, i) * (N - 1);
    int t = maxx - res + 1;
    while(n)
    {
        n --;
        int p = t / pow(N, n);
        t %= (int)pow(N, n);
        printf("%c", (char)(p + 'a'));
    }
    return 0;
}

7-7 出租

题目:

下面是新浪微博上曾经很火的一张图:2024年天梯赛训练赛1-10题:题目题解与思想解析(C++简化版)_第1张图片

一时间网上一片求救声,急问这个怎么破。其实这段代码很简单,index数组就是arr数组的下标,index[0]=2 对应 arr[2]=1index[1]=0 对应 arr[0]=8index[2]=3 对应 arr[3]=0,以此类推…… 很容易得到电话号码是18013820100

本题要求你编写一个程序,为任何一个电话号码生成这段代码 —— 事实上,只要生成最前面两行就可以了,后面内容是不变的。

输入格式:

输入在一行中给出一个由11位数字组成的手机号码。

输出格式:

为输入的号码生成代码的前两行,其中arr中的数字必须按递减顺序给出。

题解:

1、这道题考察字符的映射,我在这里转换成了数组的映射。

2、通过创建两个整形数组,分别是字典arr和被映射对象indexx。

3、通过减‘0’操作,将字符转换为整形数字,并且使用st存储出现过的数字,用于按照题目要求从大到小创建字典。

4、对字典整理完成后,就可以倒推出被映射对象了。

#include
using namespace std;
const int N = 20;
bool st[N];
int arr[N], indexx[N];
int main()
{
    int idx = 0;
    string s; cin >> s;
    int n = s.size();
    memset(st, false, sizeof st);
    for(int i = 0; i < n; i ++)
    {
        int t = s[i] - '0';
        st[t] = true;
    }
    for(int i = 9; i >= 0; i --)
    { 
        if(st[i])
        {
            arr[idx ++] = i;
        }
    }
    for(int i = 0; i < n; i ++)
    {
        int t = s[i] - '0';
        for(int j = 0; j < idx; j ++)
        {
            if(arr[j] == t){
                indexx[i] = j;
                break;
            }
        }
    }
    cout << "int[] arr = new int[]{" << arr[0];
    for(int i = 1; i < idx; i ++)
    {
        cout <<  ',' << arr[i];
    }
    cout << "};" << endl;
    cout << "int[] index = new int[]{" << indexx[0];
    for(int i = 1; i < 11; i ++)
    {
        cout <<  ',' <

7-8 分寝室

题目:

学校新建了宿舍楼,共有 n 间寝室。等待分配的学生中,有女生 n0​ 位、男生 n1​ 位。所有待分配的学生都必须分到一间寝室。所有的寝室都要分出去,最后不能有寝室留空。
现请你写程序完成寝室的自动分配。分配规则如下:

  • 男女生不能混住;
  • 不允许单人住一间寝室;
  • 对每种性别的学生,每间寝室入住的人数都必须相同;例如不能出现一部分寝室住 2 位女生,一部分寝室住 3 位女生的情况。但女生寝室都是 2 人一间,男生寝室都是 3 人一间,则是允许的;
  • 在有多种分配方案满足前面三项要求的情况下,要求两种性别每间寝室入住的人数差最小。

输入格式:

输入在一行中给出 3 个正整数 n0​、n1​、n,分别对应女生人数、男生人数、寝室数。数字间以空格分隔,均不超过 105。

输出格式:

在一行中顺序输出女生和男生被分配的寝室数量,其间以 1 个空格分隔。行首尾不得有多余空格。
如果有解,题目保证解是唯一的。如果无解,则在一行中输出 No Solution

题解:

1、这道题考察区间分配,创建l和r分别表示左右边界。

2、用i和j表示临时的区间l和r,采用for循环遍历,找到l和r差值最小的时候,便是答案。

#include
using namespace std;
int main(){
    int a, b, n; cin >> a >> b >> n;
    int l = 0, r = n;
    int ans = 0x3f3f3f3f;
    if(a == 1 || b == 1) cout << "No Solution";
    for(int i = 1; i < n; i ++)
    {
        int j = n - i;
        if(a % i == 0 && b % j == 0)
        {
            int t1 = a / i, t2 = b / j;
            if(t1 == 1 || t2 == 1) continue;
            if(ans > abs(t1 - t2))
            {
                ans = abs(t1 - t2);
                l = i, r = j;
            }
        }
    }
    if(l == 0) cout << "No Solution";
    else cout << l << ' ' << r;
}

7-9 彩虹瓶

题目:

彩虹瓶的制作过程(并不)是这样的:先把一大批空瓶铺放在装填场地上,然后按照一定的顺序将每种颜色的小球均匀撒到这批瓶子里。

假设彩虹瓶里要按顺序装 N 种颜色的小球(不妨将顺序就编号为 1 到 N)。现在工厂里有每种颜色的小球各一箱,工人需要一箱一箱地将小球从工厂里搬到装填场地。如果搬来的这箱小球正好是可以装填的颜色,就直接拆箱装填;如果不是,就把箱子先码放在一个临时货架上,码放的方法就是一箱一箱堆上去。当一种颜色装填完以后,先看看货架顶端的一箱是不是下一个要装填的颜色,如果是就取下来装填,否则去工厂里再搬一箱过来。

如果工厂里发货的顺序比较好,工人就可以顺利地完成装填。例如要按顺序装填 7 种颜色,工厂按照 7、6、1、3、2、5、4 这个顺序发货,则工人先拿到 7、6 两种不能装填的颜色,将其按照 7 在下、6 在上的顺序堆在货架上;拿到 1 时可以直接装填;拿到 3 时又得临时码放在 6 号颜色箱上;拿到 2 时可以直接装填;随后从货架顶取下 3 进行装填;然后拿到 5,临时码放到 6 上面;最后取了 4 号颜色直接装填;剩下的工作就是顺序从货架上取下 5、6、7 依次装填。

但如果工厂按照 3、1、5、4、2、6、7 这个顺序发货,工人就必须要愤怒地折腾货架了,因为装填完 2 号颜色以后,不把货架上的多个箱子搬下来就拿不到 3 号箱,就不可能顺利完成任务。

另外,货架的容量有限,如果要堆积的货物超过容量,工人也没办法顺利完成任务。例如工厂按照 7、6、5、4、3、2、1 这个顺序发货,如果货架够高,能码放 6 只箱子,那还是可以顺利完工的;但如果货架只能码放 5 只箱子,工人就又要愤怒了……

本题就请你判断一下,工厂的发货顺序能否让工人顺利完成任务。

输入格式:

输入首先在第一行给出 3 个正整数,分别是彩虹瓶的颜色数量 N(1

随后 K 行,每行给出 N 个数字,是 1 到N 的一个排列,对应工厂的发货顺序。

一行中的数字都以空格分隔。

输出格式:

对每个发货顺序,如果工人可以愉快完工,就在一行中输出 YES;否则输出 NO

题解:

1、考察入栈和出栈,栈内空间检查。

#include
using namespace std;
const int N = 1e3 + 10;
int q[N];
int main()
{
    int n, m, k; cin >> n >> m >> k;
    while(k --)
    {
        int q_idx = 0;
        int idx = 1;
        int p = 0;
        bool st = true;
        for(int i = 1; i <= n; i ++)
        {
            if(q_idx){
                p = q[q_idx];
            }
            if(p == idx){
                q_idx --;
                idx ++;
                i --;
                
                continue;
            }
            int t; cin >> t;
            if(t == idx) {
            
                idx ++;
            }
            else{
                q[++ q_idx] = t;
                if(q_idx > m) st = false;
            }
        }
        while(st)
        {
            if(q[q_idx --] == idx ++) continue;
            else break;
        }
        if(!st || idx <= n) cout << "NO";
        else cout <<"YES";
        cout << endl;
    }
    return 0;
}

7-10 简单计算器

题目:

本题要求你为初学数据结构的小伙伴设计一款简单的利用堆栈执行的计算器。如上图所示,计算器由两个堆栈组成,一个堆栈 S1​ 存放数字,另一个堆栈 S2​ 存放运算符。计算器的最下方有一个等号键,每次按下这个键,计算器就执行以下操作:

  1. 从 S1​ 中弹出两个数字,顺序为 n1​ 和 n2​;
  2. 从 S2​ 中弹出一个运算符 op;
  3. 执行计算 n2​ op n1​;
  4. 将得到的结果压回 S1​。

直到两个堆栈都为空时,计算结束,最后的结果将显示在屏幕上。

输入格式:

输入首先在第一行给出正整数 N(1

第二行给出 N 个绝对值不超过 100 的整数;第三行给出 N−1 个运算符 —— 这里仅考虑 +-*/ 这四种运算。一行中的数字和符号都以空格分隔。

输出格式:

将输入的数字和运算符按给定顺序分别压入堆栈 S1​ 和 S2​,将执行计算的最后结果输出。注意所有的计算都只取结果的整数部分。题目保证计算的中间和最后结果的绝对值都不超过 109。

如果执行除法时出现分母为零的非法操作,则在一行中输出:ERROR: X/0,其中 X 是当时的分子。然后结束程序。

题解:

1、现实模拟题目,通过模仿现实对计算机的操作进行编写代码。

2、题目主要通过每次判断用户输入,进行运算输出,存入n1中,一共四种判断,特判最后的除法。

#include
using namespace std;
const int N = 1e3 + 10;
int S1[N];
char S2[N];
int main()
{
    int n; cin >> n;
    for(int i = 1; i <= n; i ++) cin >> S1[i];
    for(int i = 1; i < n; i ++) cin >> S2[i];
    int n1, n2; n1 = S1[n];
    for(int i = n - 1; i >= 1; i --)
    {
        char c = S2[i];
        n2 = S1[i];
        if(c == '+')
        {
            n1 += n2;
        }
        else if(c == '-')
        {
            n1 = n2 - n1;
        }
        else if(c == '*')
        {
            n1 = n2 * n1;
        }
        else {
            if(n1 == 0)
            {
                printf("ERROR: %d/0", n2);
                return 0;
            }
            n1 = n2 / n1;
        }
    }
    cout << n1;
}

你可能感兴趣的:(c++,算法,开发语言)