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 <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
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 <cstdio>
#include <cstdlib>
#include <cmath>
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 <cstdio>
#include <cstring>
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 <cstdio>
#include <cstring>
#include <cmath>
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 <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
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 <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
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 <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
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 <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
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);
}
}