2018 团体程序设计天梯赛 部分题解

第一阶段我拿到了77分,第一题没做,还有一个规律题被部分样例hack了,第二阶段有一个结构体快排的题也是部分样例hack,这道25分的题我拿了18分,一共拿到了95分,传一下部分题解。

L1-2 倒数第N个字符串(15 分)

给定一个完全由小写英文字母组成的字符串等差递增序列,该序列中的每个字符串的长度固定为 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 个字符串。题目保证这个字符串是存在的。

输入样例:

3 7417

输出样例:

pat

思路:莫名规律被hack...

12分的代码:

#include
#include
#include
#include
#include
using namespace std;
int a, b;
char s[7];

int main() {
    scanf("%d %d", &a, &b);
    for(int i = 0; i < a; i++) s[i] = 'z';
    int t = a;
    while(b && t) {
        s[t - 1] -= b % 26;
        b /= 26;
        t--;
    }
    s[a - 1]++;
    printf("%s\n", s);

}


L1-3 打折(5 分)

去商场淘打折商品时,计算打折以后的价钱是件颇费脑子的事情。例如原价 ¥988,标明打 7 折,则折扣价应该是 ¥988 x 70% = ¥691.60。本题就请你写个程序替客户计算折扣价。

输入格式:

输入在一行中给出商品的原价(不超过1万元的正整数)和折扣(为[1, 9]区间内的整数),其间以空格分隔。

输出格式:

在一行中输出商品的折扣价,保留小数点后 2 位。

输入样例:

988 7

输出样例:

691.60

思路:水题

AC代码:

#include
#include
#include
using namespace std;
int x, y;
double ans;

int main() {
    scanf("%d %d", &x, &y);
    ans = x * y * 1.0 / 10;
    printf("%.2lf\n", ans);

}


L1-4 2018我们要赢(5 分)

2018年天梯赛的注册邀请码是“2018wmyy”,意思就是“2018我们要赢”。本题就请你用汉语拼音输出这句话。

输入格式:

本题没有输入。

输出格式:

在第一行中输出:“2018”;第二行中输出:“wo3 men2 yao4 ying2 !”。

输入样例:

本题没有输入。

输出样例:

2018
wo3 men2 yao4 ying2 !

思路:不能再水了

AC代码:

#include
#include
using namespace std;

int main() {
    puts("2018");
    puts("wo3 men2 yao4 ying2 !");

}


L1-5 电子汪(10 分)

据说汪星人的智商能达到人类 4 岁儿童的水平,更有些聪明汪会做加法计算。比如你在地上放两堆小球,分别有 1 只球和 2 只球,聪明汪就会用“汪!汪!汪!”表示 1 加 2 的结果是 3。

本题要求你为电子宠物汪做一个模拟程序,根据电子眼识别出的两堆小球的个数,计算出和,并且用汪星人的叫声给出答案。

输入格式:

输入在一行中给出两个 [1, 9] 区间内的正整数 A 和 B,用空格分隔。

输出格式:

在一行中输出 A + B 个Wang!

输入样例:

2 1

输出样例:

Wang!Wang!Wang!

思路:继续送人头

AC代码:

#include
#include
#include
using namespace std;
int a, b;

int main() {
    scanf("%d %d", &a, &b);
    for(int i = 1; i <= a + b; i++) printf("Wang!");

}


L1-6 福到了(15 分)

“福”字倒着贴,寓意“福到”。不论到底算不算民俗,本题且请你编写程序,把各种汉字倒过来输出。这里要处理的每个汉字是由一个 N × N 的网格组成的,网格中的元素或者为字符 @ 或者为空格。而倒过来的汉字所用的字符由裁判指定。

输入格式:

输入在第一行中给出倒过来的汉字所用的字符、以及网格的规模 N (不超过100的正整数),其间以 1 个空格分隔;随后 N 行,每行给出 N 个字符,或者为 @ 或者为空格。

输出格式:

输出倒置的网格,如样例所示。但是,如果这个字正过来倒过去是一样的,就先输出bu yong dao le,然后再用输入指定的字符将其输出。

输入样例 1:

$ 9
 @  @@@@@
@@@  @@@ 
 @   @ @ 
@@@  @@@ 
@@@ @@@@@
@@@ @ @ @
@@@ @@@@@
 @  @ @ @
 @  @@@@@

输出样例 1:

$$$$$  $ 
$ $ $  $ 
$$$$$ $$$
$ $ $ $$$
$$$$$ $$$
 $$$  $$$
 $ $   $ 
 $$$  $$$
$$$$$  $

输入样例 2:

& 3
@@@
 @ 
@@@

输出样例 2:

bu yong dao le
&&&
 & 
&&&

思路:二维gets( )读入空格,最开始getchar( )即可,换字符时,对空格单独特判即可。

AC代码:

#include
#include
#include
#include
#include
using namespace std;
char c;
int n;
char s[105][105];
char ans[105][105];
bool flg;

int main() {
    scanf(" %c %d", &c, &n);
    getchar();
    for(int i = 0; i < n; i++) gets(s[i]);
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) ans[i][j] = s[n - 1 - i][n - 1 - j];
    }
    flg = 1;
    for(int i = 0; i < n; i++) {
        if(strcmp(ans[i], s[i]) != 0) {
            flg = 0; break;
        }
    }
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            if(ans[i][j] != ' ') ans[i][j] = c;
        }
    }
    if(flg) puts("bu yong dao le");
    for(int i = 0; i < n; i++) puts(ans[i]);

}


L1-7 谁是赢家(10 分)

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

输入格式:

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

输出格式:

按以下格式输出赢家:

The winner is x: P1 + P2

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

输入样例:

327 129
1 0 1

输出样例:

The winner is a: 327 + 1

思路:根据题意暴力即可。

AC代码:

#include
#include
#include
#include
#include
using namespace std;
int x, y;
int a, b, c;
bool flg;
int cntx, cnty;

int main() {
    scanf("%d %d %d %d %d", &x, &y, &a, &b, &c);
    if(x > y) {
        cntx = 0;
        if(a == 0 || b == 0 || c == 0) {
            flg = 1;
            if(a == 0) cntx++;
            if(b == 0) cntx++;
            if(c == 0) cntx++;
        }
        else {
            flg = 0;
            cnty = 3;
        }
    }
    else if(x < y) {
        cnty = 0;
        if(a == 0 && b == 0 && c == 0) {
            flg = 1;
            cntx = 3;
        }
        else {
            flg = 0;
            if(a == 1) cnty++;
            if(b == 1) cnty++;
            if(c == 1) cnty++;
        }
    }
    if(flg) printf("The winner is a: %d + %d\n", x, cntx);
    else printf("The winner is b: %d + %d\n", y, cnty);

}


L1-8 猜数字(20 分)

一群人坐在一起,每人猜一个 100 以内的数,谁的数字最接近大家平均数的一半就赢。本题就要求你找出其中的赢家。

输入格式:

输入在第一行给出一个正整数N(104)。随后 N 行,每行给出一个玩家的名字(由不超过8个英文字母组成的字符串)和其猜的正整数( 100)。

输出格式:

在一行中顺序输出:大家平均数的一半(只输出整数部分)、赢家的名字,其间以空格分隔。题目保证赢家是唯一的。

输入样例:

7
Bob 35
Amy 28
James 98
Alice 11
Jack 45
Smith 33
Chris 62

输出样例:

22 Amy

思路:根据题意暴力即可。

AC代码:

#include
#include
#include
#include
#include
using namespace std;
const int Maxx = 1e4 + 7;
const int Inf = 1e9 + 7;
int n;
char s[Maxx][15];
int a[Maxx];

int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%s %d", s[i], &a[i]);
    int sum = 0, aver;
    for(int i = 1; i <= n; i++) sum += a[i];
    aver = (sum / n) / 2;
    int minT = Inf;
    int ans;
    for(int i = 1; i <= n; i++) {
        minT = min(minT, abs(a[i] - aver));
    }
    for(int i = 1; i <= n; i++) {
        if(abs(a[i] - aver) == minT) {
            ans = i;
            break;
        }
    }
    printf("%d %s\n", aver, s[ans]);

}


L2-3 名人堂与代金券(25 分)

对于在中国大学MOOC(http://www.icourse163.org/ )学习“数据结构”课程的学生,想要获得一张合格证书,总评成绩必须达到 60 分及以上,并且有另加福利:总评分在 [G, 100] 区间内者,可以得到 50 元 PAT 代金券;在 [60, G) 区间内者,可以得到 20 元PAT代金券。全国考点通用,一年有效。同时任课老师还会把总评成绩前 K 名的学生列入课程“名人堂”。本题就请你编写程序,帮助老师列出名人堂的学生,并统计一共发出了面值多少元的 PAT 代金券。

输入格式:

输入在第一行给出 3 个整数,分别是 N(不超过 10 000 的正整数,为学生总数)、G(在 (60,100) 区间内的整数,为题面中描述的代金券等级分界线)、K(不超过 100 且不超过 N 的正整数,为进入名人堂的最低名次)。接下来 N 行,每行给出一位学生的账号(长度不超过15位、不带空格的字符串)和总评成绩(区间 [0, 100] 内的整数),其间以空格分隔。题目保证没有重复的账号。

输出格式:

首先在一行中输出发出的 PAT 代金券的总面值。然后按总评成绩非升序输出进入名人堂的学生的名次、账号和成绩,其间以 1 个空格分隔。需要注意的是:成绩相同的学生享有并列的排名,排名并列时,按账号的字母序升序输出。

输入样例:

10 80 5
[email protected] 78
[email protected] 87
[email protected] 65
[email protected] 96
[email protected] 39
[email protected] 87
[email protected] 80
[email protected] 88
[email protected] 80
[email protected] 70

输出样例:

360
1 [email protected] 96
2 [email protected] 88
3 [email protected] 87
3 [email protected] 87
5 [email protected] 80
5 [email protected] 80

思路:结构体快排的裸题,但是莫名被hack,欢迎各位大佬帮我查查bug

18分代码:

#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 7;
int n, g, k;

struct PP {
    char s[40];
    int a; //分数
    int num; //排名
} per[maxn];

bool cmp(PP x, PP y) {
    if(x.a == y.a) {
        if(strcmp(x.s, y.s) < 0) return strcmp(x.s, y.s);
    }
    return x.a > y.a;
}

int main() {
    scanf("%d %d %d", &n, &g, &k);
    for(int i = 1; i <= n; i++) scanf("%s %d", per[i].s, &per[i].a); //传值
    
    int cnt = 0;
    for(int i = 1; i <= n; i++) {
        if(per[i].a >= g && per[i].a <= 100) cnt += 50;
        else if(per[i].a >= 60 && per[i].a < g) cnt += 20;
    } //计分

    sort(per + 1, per + n + 1, cmp);
    for(int i = 1; i <= n; i++) {
        if(per[i].a == per[i - 1].a) per[i].num = i - 1;
        else per[i].num = i;
    } //排名

    printf("%d\n", cnt);
    for(int i = 1; i <= n; i++) {
        if(per[i].num <= k) printf("%d %s %d\n", per[i].num, per[i].s, per[i].a);
    }
}

你可能感兴趣的:(水题合集)