1. 程式人生 > >2018 團體程式設計天梯賽 部分題解

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);
    }
}