当前位置:   article > 正文

[PTA]2021天梯赛-总决赛 L1题解合集_c语言降价提醒机器人

c语言降价提醒机器人

前言说明

题集连接: 团体程序设计天梯赛-练习集

L1的题号从L1-73到L-80

代码可以无限提交,当场出分。比ACM赛制好很多。

虽说是团队赛,但这个团队指的是最后团队所有人的分数总和,现场还是个人编程做题。不是像ACM一样三人一队的形式。且最后还会评个人总分。就是说你可以难道两张证。

L1的题目总分100分,一队10人。只有团队总分到达800分时,才能进入L2部分。(L2可写,但不满800不计入团队总分,但能计入个人总分)

题解

以下代码全部通过测试

人与神 (5 分)

人与神 (5 分)

解读

直接输出字符串To iterate is human, to recurse divine.即可。换不换行都能通过。

代码

#include <bits/stdc++.h>
using namespace std;

int main (void)
{
    cout << "To iterate is human, to recurse divine." << endl;
    
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

小结

这题的难度就是直接打印Hello World的级别。

赛场上做本题最大的收获是,知道了不要刚开考就点进5分题!因为刚开考的时候全国的选手都在进入系统,会崩溃。建议进入后直接点个15,或20分左右题看看。不然在等系统恢复时候你就是在干等浪费时间!


两小时学完C语言 (5 分)

两小时学完C语言 (5 分)

解读

直接输入后输出n-k*m即可。

代码

#include <bits/stdc++.h>
using namespace std;

int main (void)
{
    int n, k, m;
    cin >> n >> k >> m;
    
    cout << n-k*m << endl;
    
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

小结

由于本题只是一个5分题,k*m不会超出int范围,且题干里明确表明了看过的总字数不会超过n,所以就不用考虑n<0的情况。

但是这些细节是我们平时在做题的时候自己就该一下子联想到的。


强迫症 (10 分)

强迫症 (10 分)

解读

对于数字型的输入方法式,我们不但可以直接输入数字,还可以以字符串的方式输入。

分别根据串长为4或6进行处理。

最后输出可以直接输出一个串,也可以以三部分 年+“-”+月进行输出。

代码

#include <bits/stdc++.h>
using namespace std;

int main (void)
{
    string s;
    cin >> s;
    int len = s.size();
    
    if (len == 6){  //输入6位
        s.insert(4, "-");
    }else{          //输入4位
        s.insert(2, "-");
        string nian = s.substr(0, 2);
        int num = stoi(nian);
        if (num < 22){
            s.insert(0, "20");
        }else{
            s.insert(0, "19");
        }
    }
    
    cout << s << endl;
    
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

此处对于串长为6的,直接在串中插入“-”即可。

对于串长为4的,还要先截取前两位的年份,进行判断,再把完整年份放入串中。

小结

s.insert(pos str); 在该串的pos位置后面插入str

s.substr(pos, len); 在该串的pos位置起,获取长度为len的字串

stoi(str); 将字符串转换成int 同理还有stod(double), stoll(long long)等等


降价提醒机器人 (10 分)

降价提醒机器人 (10 分)

解读

本质还是比较数值大小,还要注意小数的输出。

代码

#include <bits/stdc++.h>
using namespace std;

int main (void)
{
    int n;
    double price;
    cin >> n >> price;
    
    double cmp_price;
    while(n--){
        cin >> cmp_price;
        if (price - cmp_price > 0){
//             printf("On Sale! %.1lf\n", cmp_price);
            cout << "On Sale! " << fixed << setprecision(1) << cmp_price << endl; 
        }
    }
    
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

小结

两种小数的输出方式,显然第一种printf型的好用,cout型的太难记了

printf(“On Sale! %.1lf\n”, cmp_price);
cout << "On Sale! " << fixed << setprecision(1) << cmp_price << endl;

。。。当时场上我cout型不会拼,而cout用太多,printf型的转义符等参数忘了哪个跟哪个对应。慌的一比。。。

最后急中生智之下。通过利用cout是输出有效位这一特点解决

double a = 1.0; cout << a << endl; 输出的是1

double b = 1.1; cout << b << endl ; 输出的是1.1

然后我通过把数值是否是整数来判断输出。(惊险)

判断方法式很多,我用的ceil和floor,上下取整是否相同判断

double a = 1.1;

cout << ceil(a) << endl; 输出的是2

cout << floor(a) << endl; 输出的是1,效果等同(int)a;


大笨钟的心情 (15 分)

大笨钟的心情 (15 分)

解读

传统题目,大笨钟。本质就是给串数字,根据下标来进行访问。如果下标越界,则停止程序。

代码

#include <bits/stdc++.h>
using namespace std;

inline bool check(int num){
    return num >= 0 && num <= 23;
}

int main (void)
{
    int arr[24];
    for (int i = 0; i < 24; i++){
        cin >> arr[i];
    }
    
    int ask;
//     while(cin >> ask)
    while(scanf("%d", &ask) != EOF){
        if (!check(ask))    break;
//         string s = arr[ask] > 50 ? "Yes" : "No";
//         cout << arr[ask] << " " << s << endl;
        printf("%d %s\n", arr[ask], arr[ask] > 50 ? "Yes" : "No");
    }
    
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

小结

如果说上面那题还是在考输入规定组数的数据,那本题就是很明显的多组输入。顺便提下printf可以用三元表达式(cout不行)

多组输入

while(cin >> ask)
while(scanf("%d", &ask) != EOF)

取消输入CTRL+Z

printf+三元表达式

printf("%d %s\n", arr[ask], arr[ask] > 50 ? “Yes” : “No”);


吉老师的回归 (15 分)

吉老师的回归 (15 分)

解读

计数性题目,如果串中有qiandao 或者 easy那可以不用计数。

当m不够计数时,则当前串就是需要输出的串。

如果到最后m还可以继续计数,则输出Wo AK le

代码

#include <bits/stdc++.h>
using namespace std;

int main (void)
{
    int n, m;
    //共n题,已做m题
    cin >> n >> m;
    getchar();
    
    string s;
    string ans = "Wo AK le";
    while(n--){
        getline(cin, s);
        
        if (s.find("easy") != -1 || s.find("qiandao") != -1)
            continue;
        else{
            if (m == 0){
                ans = s;
                break;
            }else{
                m--;
            }
        }
    }
    
    cout << ans << endl;
    
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

小结

本题在输入方面考察了在非串或字符输入中间要考虑会回车的问题。通常有两种对应方式用getchar()吃掉这个回车,或者刷新一下缓冲区,这个涉及到一定输入输出流的知识点,就算法而言不怎么熟悉,所以用getchar()比较多。

还有pta这里的c++好像不支持gets();的输入了

getline(cin, s); 带空格输入string

s.find(str); 返回的是找到str或者单个字符的首次出现位置,如果没找到则返回-1

还有一点注意,OJ平台只检测我们的输出结果,所以没有把该输入的都输入到我们的程序中,就终止程序也是可以的。


天梯赛的善良 (20 分)

天梯赛的善良 (20 分)

解读

给定n个数值。正整数 N(≤2×10^4)

要求输出最小值及个数,最大值及个数

代码

数组排序版

#include <bits/stdc++.h>
using namespace std;

int main (void)
{
    int n;
    cin >> n;
    vector<int>arr(n);
    
    for (int i = 0; i < n; i++){
       cin >> arr[i];
    }
    sort(arr.begin(), arr.end());
    
    int minNum = 0;
    for (int i = 0; i < n && arr[i] == arr[0]; i++){
        minNum++;
    }
    cout << arr[0] << " " << minNum << endl;
    
    int maxNum = 0;
    for (int i = n-1; i >= 0 && arr[i] == arr[n-1]; i--){
        maxNum++;
    }
    cout << arr[n-1] << " " << maxNum << edl;
    
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

map版

#include <bits/stdc++.h>
using namespace std;

int main (void)
{
    int n;
    cin >> n;
    map<int, int>mp;

    int num;
    while(n--){
        cin >> num;
        mp[num]++;
    }

    auto its = mp.begin();
    cout << its->first << " " << its->second << endl;
    // begin() 和 rbegin() 的类型不同
    auto ite = mp.rbegin();
    cout << ite->first << " " << ite->second << endl;
    
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

小结

这题确实太善良了,我他跟没怎么读懂题,或说怎么读题。直接看输入输出的格式样例,就把题目AC了。

当时提交时候还以为会有什么细节在题干中。。。没想到过几秒告诉我AC了。。。

在排序版中,注意sort是默认从小打大,且最后在计数时加一个判断可以避免遍历完整个数组

在map版中,注意end()是最后一个元素的后一个位置,所以要往前退一个位置才能访问最后的元素。

顺便提一下,当容器元素为0时 begin() == end() 但本题明确是正整数就不用担忧这点了。


乘法口诀数列 (20 分)

乘法口诀数列 (20 分)

解读

其实样例说的很清除

2 3 10

2 3 6 1 8 6 8 4 8 4

数列前 2 项为 2 和 3。从 2 开始,因为 2×3=6,所以第 3 项是 6。因为 3×6=18,所以第 4、5 项分别是 1、8。依次类推…… 最后因为第 6 项有 6×8=48,对应第 10、11 项应该是 4、8。而因为只要求输出前 10 项,所以在输出 4 后结束。

乍一看还是处理数值的题目,再想一下各个步骤,分解乘出的数字,再计数,再用 双指针每次一个单位的移动计算。其实也不难,但是烦。

怎么化简操作呢?我们注意到一点,就是每项是一个个位数!那正好可以用字符串来处理。每个字符就是一个“数”。

string有丰富的库函数可以使用,这里使用的是C++11的新增的to_string可以将数值转化成string。然后不断连接串,再判断串长<n即可

代码

#include <bits/stdc++.h>
using namespace std;

int main (void)
{
    int a1, a2, n;
    cin >> a1 >> a2 >> n;
    
    string s;
    s += to_string(a1);
    s += to_string(a2);
    
    for (int left = 0, right = 1; s.size() < n; left++, right++){
        int num_tmp = (s[left]-'0')*(s[right]-'0');
        s += to_string(num_tmp);
    }
    
    for (int i = 0; i < n; i++){
        cout << s[i];
        if (i+1 < n)    cout << " ";
    }
    
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

小结

赛场上直接读题后,没看样例解释,理解错了,浪费了好多时间。

最后还是用数值的处理方式写的,写的又臭又长,影响了一定的心态。。。

题目固然重要,但是样例解释更重要!

注意字符char本质是一个0~127的存储的数值

to_string(number); 将数值型转换成string

关于pta的输出 其实pta在最后是否是换行并不严格,但是对于最后输出一串数组的时候,通常要求最后一项后面没有宫格

这里给出四种常见处理方式

    //法一
	for (int i = 0; i < n; i++){
        cout << s[i];
        if (i+1 < n)    cout << " ";
    }
	//法二
    for (int i = 0; i < n; i++){
        if (i+1 < n)
            cout << s[i] << " ";
        else
            cout << s[i];
    }
	//法三
    for (int i = 0; i < n-1; i++){
        cout << s[i] << " ";
    }
    cout << s[n-1] ;
    //法四
    for (int i = 0; i < n; i++){
        cout << s[i] << " \n"[i+1 == n];
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

总结

天梯赛L1的题目总体还是很基础的,也会有分值的标明难度划分的比较明确。

到了现场比赛要有一定策略,比如不要一进入系统就点开看5分,10分的题,会很亏。如果进去了页面也直接崩了,那就把体面复制到编译器里。比赛规定不能打开txt,word之类得文档。

如果有部分题的个别测试样例没有过的话,不要太心急,先检查下有没有什么特殊条件没有考虑,特别是边界问题之类的。但如果死磕不出来也不要太钻牛角尖了。看看队友答得怎么样,只要全队分数满800就行了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/232690
推荐阅读
相关标签
  

闽ICP备14008679号