2021天梯赛题解
2021程序設計天梯賽在4月24日舉辦,本文是天梯賽的部分題解,有的問題在當時也沒有得到滿分,由于學校開啟了天梯賽的重現比賽,再寫一寫。
注意:本文答案不是標準答案,每道題收獲的分數寫在了相應位置,注意查看。
有的人退出,有的人加入。始終如一,不忘初心。
L1-1 人與神 ( 5分 / 5 分) 第一個5分是代碼獲得的分數,第二個5分是題目總分,下同
跨界大神 L. Peter Deutsch 有一句名言:“To iterate is human, to recurse divine.”(迭代的是人,遞歸的是神)。本題就請你直接在屏幕上輸出這句話。
輸入格式:
本題沒有輸入。輸出格式:
在一行中輸出
輸入樣例:
無輸出樣例:
To iterate is human, to recurse divine.【問題分析】簽到題,直接輸出即可。
#include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <cstring> #include <sstream> #include <stdlib.h> #include <map> #include <stack> #include <queue> #include <vector> using namespace std; int main(){cout<<"To iterate is human, to recurse divine."<<endl;system("pause");return 0; }L1-2 兩小時學完C語言 (5分 / 5 分)
知乎上有個寶寶問:“兩個小時內如何學完 C 語言?”當然,問的是“學完”并不是“學會”。假設一本 C 語言教科書有 N 個字,這個寶寶每分鐘能看 K 個字,看了 M 分鐘。還剩多少字沒有看?
輸入格式
輸入在一行中給出 3 個正整數,分別是 N(不超過 400 000),教科書的總字數;K(不超過 3 000),是寶寶每分鐘能看的字數;M(不超過 120),是寶寶看書的分鐘數。題目保證寶寶看完的字數不超過 N。
輸出格式:
在一行中輸出寶寶還沒有看的字數。輸入樣例:
100000 1000 72輸出樣例:
28000【問題分析】大家千萬不要像這位寶寶一樣浮躁,簡單的算數題,n-k*m即可;
#include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <cstring> #include <sstream> #include <stdlib.h> #include <map> #include <stack> #include <queue> #include <vector> using namespace std; typedef long long ll; int main(){int n,m,k;cin>>n>>m>>k;cout<<n-m*k<<endl;return 0; }L1-3 強迫癥 (10分 / 10 分)
小強在統計一個小區里居民的出生年月,但是發現大家填寫的生日格式不統一,例如有的人寫 199808,有的人只寫 9808。有強迫癥的小強請你寫個程序,把所有人的出生年月都整理成 年年年年-月月 格式。對于那些只寫了年份后兩位的信息,我們默認小于 22 都是 20 開頭的,其他都是 19 開頭的。
輸入格式:
輸入在一行中給出一個出生年月,為一個 6 位或者 4 位數,題目保證是 1000 年 1 月到 2021 年 12 月之間的合法年月。輸出格式:
在一行中按標準格式 年年年年-月月 將輸入的信息整理輸出。輸入樣例 1:
9808輸出樣例 1:
1998-08輸入樣例 2:
0510輸出樣例 2:
2005-10輸入樣例 3:
196711輸出樣例 3:
1967-11【問題分析】對于本題,可以看到輸入可以分為兩種格式:
- 年份全拼,字符串一共為6位;
- 年份不全拼,只寫后兩位,字符串一共為4位;而對于這種字符串,根據題目描述 我們默認小于 22 都是 20 開頭的,其他都是 19 開頭的又可以分為兩種情況:
- 年份小于22的為21世紀年份;
- 其他的都為20世紀年份;
本題的考點為分支結構。
#include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <cstring> #include <sstream> #include <stdlib.h> #include <map> #include <stack> #include <queue> #include <vector> using namespace std; typedef long long ll; int main(){string s;cin>>s;if (s.size()==4){ //縮寫int year = (s.at(0)-'0')*10+(s.at(1)-'0'); //拿到前兩位的值if (year<22){cout<<20;} else{cout<<19;}cout<<s.at(0)<<s.at(1)<<"-"<<s.at(2)<<s.at(3);} else{ //詳細for (int i=0;i<s.size();i++){cout<<s.at(i);if (i==3){cout<<"-";}}}return 0; }L1-4 降價提醒機器人 (10分 / 10 分)
小 T 想買一個玩具很久了,但價格有些高,他打算等便宜些再買。但天天盯著購物網站很麻煩,請你幫小 T 寫一個降價提醒機器人,當玩具的當前價格比他設定的價格便宜時發出提醒。
輸入格式:
輸入第一行是兩個正整數 N 和 M (1≤N≤100,0≤M≤1000),表示有 N 條價格記錄,小 T 設置的價格為 M。
接下來 N 行,每行有一個實數 P**i(?1000.0<P**i<1000.0),表示一條價格記錄。
輸出格式:
對每一條比設定價格 M 便宜的價格記錄 P,在一行中輸出 On Sale! P,其中 P 輸出到小數點后 1 位。
輸入樣例:
4 99 98.0 97.0 100.2 98.9輸出樣例:
On Sale! 98.0 On Sale! 97.0 On Sale! 98.9【問題分析】使用循環結構,對每一個價格紀錄進行比較,發現更便宜 的提醒即可;
本題的考點為:循環結構
#include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <cstring> #include <sstream> #include <stdlib.h> #include <map> #include <stack> #include <queue> #include <vector> using namespace std; typedef long long ll; int main(){int n;double m,p;cin>>n>>m;for (int i=0;i<n;i++){cin>>p;if (p<m){printf("On Sale! %.1lf\n",p);}}return 0; }L1-5 大笨鐘的心情 (15分 / 15 分)
有網友問:未來還會有更多大笨鐘題嗎?笨鐘回復說:看心情……本題就請你替大笨鐘寫一個程序,根據心情自動輸出回答。
輸入格式:
輸入在一行中給出 24 個 [0, 100] 區間內的整數,依次代表大笨鐘在一天 24 小時中,每個小時的心情指數。
隨后若干行,每行給出一個 [0, 23] 之間的整數,代表網友詢問笨鐘這個問題的時間點。當出現非法的時間點時,表示輸入結束,這個非法輸入不要處理。題目保證至少有 1 次詢問。
輸出格式:
對每一次提問,如果當時笨鐘的心情指數大于 50,就在一行中輸出 心情指數 Yes,否則輸出 心情指數 No。
輸入樣例:
80 75 60 50 20 20 20 20 55 62 66 51 42 33 47 58 67 52 41 20 35 49 50 63 17 7 3 15 -1輸出樣例:
52 Yes 20 No 50 No 58 Yes【問題分析】大笨鐘是天梯賽的常客了,伴隨了我天梯賽的三年~,今天終于知道大笨鐘原來是姥姥的自稱hhh。回歸正題,這可能是這幾年大笨鐘系列最簡單的一道題了,我們使用一個數組保存值,對給出的查詢進行數組訪問輸出即可。
本題的考點是:數組
#include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <cstring> #include <sstream> #include <stdlib.h> #include <map> #include <stack> #include <queue> #include <vector> using namespace std; typedef long long ll; int main() {int que, mood[24];for (int i = 0; i < 24; i++){cin >> mood[i];}while (1){cin >> que;if (que < 0 || que > 23){break;}cout << mood[que] << " ";if (mood[que] > 50){cout << "Yes" << endl;}else{cout << "No" << endl;}}return 0; }L1-6 吉老師的回歸 (15分 / 15 分)
曾經在天梯賽大殺四方的吉老師決定回歸天梯賽賽場啦!為了簡化題目,我們不妨假設天梯賽的每道題目可以用一個不超過 500 的、只包括可打印符號的字符串描述出來,如:Problem A: Print "Hello world!"。眾所周知,吉老師的競賽水平非常高超,你可以認為他每道題目都會做(事實上也是……)。因此,吉老師會按照順序看題并做題。但吉老師水平太高了,所以簽到題他就懶得做了(浪費時間),具體來說,假如題目的字符串里有 qiandao 或者 easy(區分大小寫)的話,吉老師看完這道題目不做。現在給定這次天梯賽總共有幾道題目以及吉老師已經做完了幾道題目,請你告訴大家吉老師現在正在做哪個題,或者吉老師已經把所有他打算做的題目做完了。
提醒:天梯賽有分數升級的規則,如果不做簽到題可能導致團隊總分不足以升級,一般的選手請千萬不要學習吉老師的酷炫行為!
輸入格式:
輸入第一行是兩個正整數 N,M (1≤M≤N≤30),表示本次天梯賽有 N 道題目,吉老師現在做完了 M 道。
接下來 N 行,每行是一個符合題目描述的字符串,表示天梯賽的題目內容。吉老師會按照給出的順序看題——第一行就是吉老師看的第一道題,第二行就是第二道,以此類推。
輸出格式:
在一行中輸出吉老師當前正在做的題目對應的題面(即做完了 M 道題目后,吉老師正在做哪個題)。如果吉老師已經把所有他打算做的題目做完了,輸出一行 Wo AK le。
輸入樣例 1:
5 1 L1-1 is a qiandao problem. L1-2 is so...easy. L1-3 is Easy. L1-4 is qianDao. Wow, such L1-5, so easy.輸出樣例 1:
L1-4 is qianDao.輸入樣例 2:
5 4 L1-1 is a-qiandao problem. L1-2 is so easy. L1-3 is Easy. L1-4 is qianDao. Wow, such L1-5, so!!easy.輸出樣例 2:
Wo AK le【問題分析】字符串處理,主要的思路是給定一個值M代表已經做完的題目,而題目中如果出現了"qiandao"和"easy"的字眼就會被忽略(注意大小寫敏感),因此我們只需要經過一個不包含上述兩個子串的字符串就對m減一,直到m等于0或者AK(All Killed)了全部題目為止(這句話其實重復包含了m等于0且AK的情況,忽略細節~)。
本題的考點為:字符串處理;
#include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <cstring> #include <sstream> #include <stdlib.h> #include <map> #include <stack> #include <queue> #include <vector> using namespace std; typedef long long ll; int main() {int n,m;cin>>n>>m;string in;getchar();for (int i=0;i<n;i++){getline(cin,in);if (in.find("qiandao")!=in.npos||in.find("easy")!=in.npos){continue;}m--;if (m<0){cout<<in<<endl;return 0;}}cout<<"Wo AK le"<<endl;return 0; }L1-7 天梯賽的善良 (20分 / 20 分)
天梯賽是個善良的比賽。善良的命題組希望將題目難度控制在一個范圍內,使得每個參賽的學生都有能做出來的題目,并且最厲害的學生也要非常努力才有可能得到高分。于是命題組首先將編程能力劃分成了 106 個等級(太瘋狂了,這是假的),然后調查了每個參賽學生的編程能力。現在請你寫個程序找出所有參賽學生的最小和最大能力值,給命題組作為出題的參考。
輸入格式:
輸入在第一行中給出一個正整數 N(≤2×104),即參賽學生的總數。隨后一行給出 N 個不超過 106 的正整數,是參賽學生的能力值。
輸出格式:
第一行輸出所有參賽學生的最小能力值,以及具有這個能力值的學生人數。第二行輸出所有參賽學生的最大能力值,以及具有這個能力值的學生人數。同行數字間以 1 個空格分隔,行首尾不得有多余空格。
輸入樣例:
10 86 75 233 888 666 75 886 888 75 666輸出樣例:
75 3 888 2【問題分析】找到數列中最小最大值并且計數,數據規模為10^4,因此可以直接排序,對于計數,我常用的方法有數組計數(優點:方便快捷;缺點:比較消耗空間,尤其是數據較多時)和結構體計數(優點:節省空間;缺點:需要寫cmp參數,使用不方便),此處使用數組計數。
本題考點為排序**、計數器
#include <iostream> #include <stdio.h> #include <math.h> #include <algorithm> #include <string.h> #include <cstring> #include <sstream> #include <stdlib.h> #include <map> #include <stack> #include <queue> #include <vector> using namespace std; typedef long long ll; int Count[1000001]; int main() {int n,s[20001];cin>>n;for (int i=0;i<n;i++){cin>>s[i];Count[s[i]]++;}sort(s,s+n);cout<<s[0]<<" "<<Count[s[0]]<<endl;cout<<s[n-1]<<" "<<Count[s[n-1]]<<endl;return 0; }L1-8 乘法口訣數列 (20分 / 20 分)
本題要求你從任意給定的兩個 1 位數字 a1 和 a2 開始,用乘法口訣生成一個數列 {a**n},規則為從 a1 開始順次進行,每次將當前數字與后面一個數字相乘,將結果貼在數列末尾。如果結果不是 1 位數,則其每一位都應成為數列的一項。
輸入格式:
輸入在一行中給出 3 個整數,依次為 a1、a2 和 n,滿足 0≤a1,a2≤9,0<n≤103。
輸出格式:
在一行中輸出數列的前 n 項。數字間以 1 個空格分隔,行首尾不得有多余空格。
輸入樣例:
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 后結束。
【問題分析】本題需要仔細讀題,現在將題目簡化:
- 數列的每一個元素是前兩個元素的積;
- 此次的積為2位的話(不可能出現3位及以上,最大9*9=81),將十位和個位拆開作為新的兩位;
L2-1 包裝機 (25分 / 25 分)
一種自動包裝機的結構如圖 1 所示。首先機器中有 N 條軌道,放置了一些物品。軌道下面有一個筐。當某條軌道的按鈕被按下時,活塞向左推動,將軌道盡頭的一件物品推落筐中。當 0 號按鈕被按下時,機械手將抓取筐頂部的一件物品,放到流水線上。圖 2 顯示了順序按下按鈕 3、2、3、0、1、2、0 后包裝機的狀態。
一種特殊情況是,因為筐的容量是有限的,當筐已經滿了,但仍然有某條軌道的按鈕被按下時,系統應強制啟動 0 號鍵,先從筐里抓出一件物品,再將對應軌道的物品推落。此外,如果軌道已經空了,再按對應的按鈕不會發生任何事;同樣的,如果筐是空的,按 0 號按鈕也不會發生任何事。
現給定一系列按鈕操作,請你依次列出流水線上的物品。
輸入格式:
輸入第一行給出 3 個正整數 N(≤100)、M(≤1000)和 Sma**x(≤100),分別為軌道的條數(于是軌道從 1 到 N 編號)、每條軌道初始放置的物品數量、以及筐的最大容量。隨后 N 行,每行給出 M 個英文大寫字母,表示每條軌道的初始物品擺放。
最后一行給出一系列數字,順序對應被按下的按鈕編號,直到 ?1 標志輸入結束,這個數字不要處理。數字間以空格分隔。題目保證至少會取出一件物品放在流水線上。
輸出格式:
在一行中順序輸出流水線上的物品,不得有任何空格。
輸入樣例:
3 4 4 GPLT PATA OMSA 3 2 3 0 1 2 0 2 2 0 -1輸出樣例:
MATA【問題分析】這是一道利用了簡單數據結構的模擬題,對于給定的N條軌道和流水線,分別是一個隊列,筐是一個棧,這是根據他們的特性判斷的;主要考察從實際中抽象并應用數據結構解決問題的能力,熟練使用STL可以為解決此問題提供大大的便利;
下面將題目簡化:
- 對于每一個軌道(隊列),按下他們對應的軌道號時,就將隊頭的元素出隊,并且彈出筐(棧)中;
- 按下0時,將筐(棧)頂 的元素放到流水線(隊列)尾部;
- 需要特別注意兩種情況:
- 筐(棧)滿之后,在下一次觸發軌道->筐的操作時需要先強制觸發"0"操作,即筐->流水線的操作;
- 在筐沒有貨物時,按下"0"不會發生任何事情;
- 當軌道沒有貨物時,按下取貨不會發生任何事情;
本題考點:隊列、棧,STL
#include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <cstring> #include <sstream> #include <stdlib.h> #include <map> #include <stack> #include <queue> #include <vector> using namespace std; typedef long long ll; int main() {int n, m, Max;cin >> n >> m >> Max;vector<queue<char> > tracks(101); //軌道stack<char> backet; //筐queue<char> sl; //streamline 流水線char k;for (int i = 1; i <= n; i++){getchar();for (int j = 0; j < m; j++){cin >> k;tracks[i].push(k);}}int op;while (1){cin>>op;if (op==-1){break;}if (op==0){ //筐->流水線(棧->隊列)if(!backet.empty()){ //筐為空不反應sl.push(backet.top());backet.pop();}} else{ //軌道->筐(隊列->棧)if (!tracks[op].empty()){ //軌道為空不反應if (backet.size()==Max){ //筐此刻滿了sl.push(backet.top());backet.pop();backet.push(tracks[op].front());tracks[op].pop();} else{backet.push(tracks[op].front());tracks[op].pop();}}}}while (!sl.empty()){cout<<sl.front();sl.pop();}return 0; }L2-2 病毒溯源 (25 分)
病毒容易發生變異。某種病毒可以通過突變產生若干變異的毒株,而這些變異的病毒又可能被誘發突變產生第二代變異,如此繼續不斷變化。現給定一些病毒之間的變異關系,要求你找出其中最長的一條變異鏈。在此假設給出的變異都是由突變引起的,不考慮復雜的基因重組變異問題 —— 即每一種病毒都是由唯一的一種病毒突變而來,并且不存在循環變異的情況。
輸入格式:
輸入在第一行中給出一個正整數 N(≤104),即病毒種類的總數。于是我們將所有病毒從 0 到 N?1 進行編號。
隨后 N 行,每行按以下格式描述一種病毒的變異情況:
k 變異株1 …… 變異株k其中 k 是該病毒產生的變異毒株的種類數,后面跟著每種變異株的編號。第 i 行對應編號為 i 的病毒(0≤i<N)。題目保證病毒源頭有且僅有一個。
輸出格式:
首先輸出從源頭開始最長變異鏈的長度。
在第二行中輸出從源頭開始最長的一條變異鏈,編號間以 1 個空格分隔,行首尾不得有多余空格。如果最長鏈不唯一,則輸出最小序列。
注:我們稱序列 { a1,?,a**n } 比序列 { b1,?,b**n } “小”,如果存在 1≤k≤n 滿足 a**i=b**i 對所有 i<k 成立,且 a**k<b**k。
輸入樣例:
10 3 6 4 8 0 0 0 2 5 9 0 1 7 1 2 0 2 3 1輸出樣例:
4 0 4 9 1【問題分析】這道題在第一眼看到的時候以為要使用并查集,實際上這是一道樹的求最長路徑的題,
突然收到計算機大賽的任務,五一后再補(挖坑)。
總結
- 上一篇: 数据结构——堆栈的C++实现
- 下一篇: 浅析Serverless