2020年HZNU天梯訓練賽 Round 8
2020年HZNU天梯訓練賽 Round 8
時間:2020.7.24 16 134
完成情況:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
√ | √ | √ | √ | √ | √ | √ | ※ | ※ | ||||||
√ 當場做出來 ※做了一半來 ✘補題補出來
7-1 地鐵一日遊 (30分)
森森喜歡坐地鐵。這個假期,他終於來到了傳說中的地鐵之城——魔都,打算好好過一把坐地鐵的癮!
魔都地鐵的計價規則是:起步價 2 元,出發站與到達站的最短距離(即計費距離)每 K 公里增加 1 元車費。
例如取 K = 10,動安寺站離魔都綠橋站為 40 公里,則車費為 2 + 4 = 6 元。
為了獲得最大的滿足感,森森決定用以下的方式坐地鐵:在某一站上車(不妨設為地鐵站 A),則對於所有車費相同的到達站,森森只會在計費距離最遠的站或線路末端站點出站,然後用森森美圖 App 在站點外拍一張認證照,再按同樣的方式前往下一個站點。
坐著坐著,森森突然好奇起來:在給定出發站的情況下(在出發時森森也會拍一張照),他的整個旅程中能夠留下哪些站點的認證照?
地鐵是鐵路運輸的一種形式,指在地下執行為主的城市軌道交通系統。一般來說,地鐵由若干個站點組成,並有多條不同的線路雙向行駛,可類比公交車,當兩條或更多條線路經過同一個站點時,可進行換乘,更換自己所乘坐的線路。舉例來說,魔都 1 號線和 2 號線都經過人民廣場站,則乘坐 1 號線到達人民廣場時就可以換乘到 2 號線前往 2 號線的各個站點。換乘不需出站(也拍不到認證照),因此森森乘坐地鐵時換乘不受限制。
輸入格式:
輸入第一行是三個正整數 N、M 和 K,表示魔都地鐵有 N 個車站 (1 ≤ N ≤ 200),M 條線路 (1 ≤ M ≤ 1500),最短距離每超過 K 公里 (1 ≤ K ≤ 106),加 1 元車費。
接下來 M 行,每行由以下格式組成:
<站點1><空格><距離><空格><站點2><空格><距離><空格><站點3> ... <站點X-1><空格><距離><空格><站點X>
其中站點是一個 1 到 N 的編號;兩個站點編號之間的距離指兩個站在該線路上的距離。兩站之間距離是一個不大於 106 的正整數。一條線路上的站點互不相同。
注意:兩個站之間可能有多條直接連線的線路,且距離不一定相等。
再接下來有一個正整數 Q (1 ≤ Q ≤ 200),表示森森嘗試從 Q 個站點出發。
最後有 Q 行,每行一個正整數 Xi,表示森森嘗試從編號為 Xi 的站點出發。
輸出格式:
對於森森每個嘗試的站點,輸出一行若干個整數,表示能夠到達的站點編號。站點編號從小到大排序。
輸入樣例:
6 2 6
1 6 2 4 3 1 4
5 6 2 6 6
4
2
3
4
5
輸出樣例:
1 2 4 5 6
1 2 3 4 5 6
1 2 4 5 6
1 2 4 5 6
7-2 PTA使我精神煥發 (5分)
以上是湖北經濟學院同學的大作。本題就請你用漢語拼音輸出這句話。
輸入格式:
本題沒有輸入。
輸出格式:
在一行中按照樣例輸出,以驚歎號結尾。
輸入樣例:
無
輸出樣例:
PTA shi3 wo3 jing1 shen2 huan4 fa1 !
PTA shi3 wo3 jing1 shen2 huan4 fa1 !
7-3 6翻了 (15分)
“666”是一種網路用語,大概是表示某人很厲害、我們很佩服的意思。最近又衍生出另一個數字“9”,意思是“6翻了”,實在太厲害的意思。如果你以為這就是厲害的最高境界,那就錯啦 —— 目前的最高境界是數字“27”,因為這是 3 個 “9”!
本題就請你編寫程式,將那些過時的、只會用一連串“6666……6”表達仰慕的句子,翻譯成最新的高階表達。
輸入格式:
輸入在一行中給出一句話,即一個非空字串,由不超過 1000 個英文字母、數字和空格組成,以回車結束。
輸出格式:
從左到右掃描輸入的句子:如果句子中有超過 3 個連續的 6,則將這串連續的 6 替換成 9;但如果有超過 9 個連續的 6,則將這串連續的 6 替換成 27。其他內容不受影響,原樣輸出。
輸入樣例:
it is so 666 really 6666 what else can I say 6666666666
輸出樣例:
it is so 666 really 9 what else can I say 27
#include<bits/stdc++.h>
using namespace std;
int main ()
{
int cnt=0;
string s;
getline(cin,s);
for(int i=0;i<s.length();i++)
{
if(s[i]=='6')cnt++;
else
{
if(cnt<=3)for(int j=0;j<cnt;j++) cout<<"6";
else if(cnt>3&&cnt<=9) cout<<"9";
else cout<<"27";
cnt=0;cout<<s[i];
}
}
if(cnt>0)
{
if(cnt<=3) for(int j=0;j<cnt;j++) cout<<"6";
else if(cnt>3&&cnt<=9) cout<<"9";
else cout<<"27";
}
return 0;
}
7-4 敲笨鍾 (20分)
微博上有個自稱“大笨鐘V”的傢伙,每天敲鐘催促碼農們愛惜身體早點睡覺。為了增加敲鐘的趣味性,還會糟改幾句古詩詞。其糟改的方法為:去網上搜尋壓“ong”韻的古詩詞,把句尾的三個字換成“敲笨鍾”。例如唐代詩人李賀有名句曰:“尋章摘句老鵰蟲,曉月當簾掛玉弓”,其中“蟲”(chong)和“弓”(gong)都壓了“ong”韻。於是這句詩就被糟改為“尋章摘句老鵰蟲,曉月當簾敲笨鍾”。
現在給你一大堆古詩詞句,要求你寫個程式自動將壓“ong”韻的句子糟改成“敲笨鍾”。
輸入格式:
輸入首先在第一行給出一個不超過 20 的正整數 N。隨後 N 行,每行用漢語拼音給出一句古詩詞,分上下兩半句,用逗號 ,
分隔,句號 .
結尾。相鄰兩字的拼音之間用一個空格分隔。題目保證每個字的拼音不超過 6 個字元,每行字元的總長度不超過 100,並且下半句詩至少有 3 個字。
輸出格式:
對每一行詩句,判斷其是否壓“ong”韻。即上下兩句末尾的字都是“ong”結尾。如果是壓此韻的,就按題面方法糟改之後輸出,輸出格式同輸入;否則輸出 Skipped
,即跳過此句。
輸入樣例:
5
xun zhang zhai ju lao diao chong, xiao yue dang lian gua yu gong.
tian sheng wo cai bi you yong, qian jin san jin huan fu lai.
xue zhui rou zhi leng wei rong, an xiao chen jing shu wei long.
zuo ye xing chen zuo ye feng, hua lou xi pan gui tang dong.
ren xian gui hua luo, ye jing chun shan kong.
輸出樣例:
xun zhang zhai ju lao diao chong, xiao yue dang lian qiao ben zhong.
Skipped
xue zhui rou zhi leng wei rong, an xiao chen jing qiao ben zhong.
Skipped
Skipped
#include<bits/stdc++.h>
using namespace std;
int main ()
{
int n,cnt,p;
cin>>n;
getchar();
while(n--)
{
string s;
getline(cin,s);cnt=0;
for(int i=0;i<s.length()-3;i++)
{
if(s[i]=='o'&&s[i+1]=='n'&&s[i+2]=='g'&&s[i+3]==',')cnt++;
if(s[i]=='o'&&s[i+1]=='n'&&s[i+2]=='g'&&s[i+3]=='.')cnt++;
}
if(cnt!=2)cout<<"Skipped"<<endl;
else
{
cnt=0;
for(int i=s.length()-1;i>=0;i--)
{
if(s[i]==' ')cnt++;
if(cnt==3){p=i;break;}
}
for(int i=0;i<=p;i++) cout<<s[i];
cout<<"qiao ben zhong."<<endl;
}
}
return 0;
}
7-5 心理陰影面積 (5分)
這是一幅心理陰影面積圖。我們都以為自己可以勻速前進(圖中藍色直線),而拖延症晚期的我們往往執行的是最後時刻的瘋狂趕工(圖中的紅色折線)。由紅、藍線圍出的面積,就是我們在做作業時的心理陰影面積。
現給出紅色拐點的座標 (x,y),要求你算出這個心理陰影面積。
輸入格式:
輸入在一行中給出 2 個不超過 100 的正整數 x 和 y,並且保證有 x>y。這裡假設橫、縱座標的最大值(即截止日和最終完成度)都是 100。
輸出格式:
在一行中輸出心理陰影面積。
友情提醒:三角形的面積 = 底邊長 x 高 / 2;矩形面積 = 底邊長 x 高。嫑想得太複雜,這是一道 5 分考減法的題……
輸入樣例:
90 10
輸出樣例:
4000
#include<bits/stdc++.h>
using namespace std;
int main ()
{
int x,y;
cin>>x>>y;
cout<<100*100/2-y*100/2-(100-x)*100/2;
return 0;
}
7-6 新胖子公式 (10分)
根據錢江晚報官方微博的報導,最新的肥胖計算方法為:體重(kg) / 身高(m) 的平方。如果超過 25,你就是胖子。於是本題就請你編寫程式自動判斷一個人到底算不算胖子。
輸入格式:
輸入在一行中給出兩個正數,依次為一個人的體重(以 kg 為單位)和身高(以 m 為單位),其間以空格分隔。其中體重不超過 1000 kg,身高不超過 3.0 m。
輸出格式:
首先輸出將該人的體重和身高代入肥胖公式的計算結果,保留小數點後 1 位。如果這個數值大於 25,就在第二行輸出 PANG
,否則輸出 Hai Xing
。
輸入樣例 1:
100.1 1.74
輸出樣例 1:
33.1
PANG
輸入樣例 2:
65 1.70
輸出樣例 2:
22.5
Hai Xing
#include<bits/stdc++.h>
using namespace std;
int main ()
{
double x,y;
cin>>x>>y;
double ans=x/(y*y);
printf("%.1f\n",ans);
if(ans>25)cout<<"PANG";
else cout<<"Hai Xing";
return 0;
}
7-7 幸運彩票 (15分)
彩票的號碼有 6 位數字,若一張彩票的前 3 位上的數之和等於後 3 位上的數之和,則稱這張彩票是幸運的。本題就請你判斷給定的彩票是不是幸運的。
輸入格式:
輸入在第一行中給出一個正整數 N(≤ 100)。隨後 N 行,每行給出一張彩票的 6 位數字。
輸出格式:
對每張彩票,如果它是幸運的,就在一行中輸出 You are lucky!
;否則輸出 Wish you good luck.
。
輸入樣例:
2
233008
123456
輸出樣例:
You are lucky!
Wish you good luck.
#include<bits/stdc++.h>
using namespace std;
int main ()
{
int n;
char s[8];
cin>>n;
while(n--)
{
cin>>s;
if(s[0]+s[1]+s[2]==s[3]+s[4]+s[5])cout<<"You are lucky!"<<endl;
else cout<<"Wish you good luck."<<endl;
}
return 0;
}
7-8 吃魚還是吃肉 (10分)
國家給出了 8 歲男寶寶的標準身高為 130 釐米、標準體重為 27 公斤;8 歲女寶寶的標準身高為 129 釐米、標準體重為 25 公斤。
現在你要根據小寶寶的身高體重,給出補充營養的建議。
輸入格式:
輸入在第一行給出一個不超過 10 的正整數 N,隨後 N 行,每行給出一位寶寶的身體資料:
性別 身高 體重
其中性別
是 1 表示男生,0 表示女生。身高
和體重
都是不超過 200 的正整數。
輸出格式:
對於每一位寶寶,在一行中給出你的建議:
- 如果太矮了,輸出:
duo chi yu!
(多吃魚); - 如果太瘦了,輸出:
duo chi rou!
(多吃肉); - 如果正標準,輸出:
wan mei!
(完美); - 如果太高了,輸出:
ni li hai!
(你厲害); - 如果太胖了,輸出:
shao chi rou!
(少吃肉)。
先評價身高,再評價體重。兩句話之間要有 1 個空格。
輸入樣例:
4
0 130 23
1 129 27
1 130 30
0 128 27
輸出樣例:
ni li hai! duo chi rou!
duo chi yu! wan mei!
wan mei! shao chi rou!
duo chi yu! shao chi rou!
#include<bits/stdc++.h>
using namespace std;
int main ()
{
int n,s,h,w;
cin>>n;
while(n--)
{
cin>>s>>h>>w;
if(s==1)
{
if(h>130)cout<<"ni li hai! ";
if(h<130)cout<<"duo chi yu! ";
if(h==130)cout<<"wan mei! ";
if(w>27)cout<<"shao chi rou!";
if(w<27)cout<<"duo chi rou!";
if(w==27)cout<<"wan mei!";
}
if(s==0)
{
if(h>129)cout<<"ni li hai! ";
if(h<129)cout<<"duo chi yu! ";
if(h==129)cout<<"wan mei! ";
if(w>25)cout<<"shao chi rou!";
if(w<25)cout<<"duo chi rou!";
if(w==25)cout<<"wan mei!";
}
cout<<endl;
}
return 0;
}
7-9 估值一億的AI核心程式碼 (20分)
以上圖片來自新浪微博。
本題要求你實現一個稍微更值錢一點的 AI 英文問答程式,規則是:
- 無論使用者說什麼,首先把對方說的話在一行中原樣打印出來;
- 消除原文中多餘空格:把相鄰單詞間的多個空格換成 1 個空格,把行首尾的空格全部刪掉,把標點符號前面的空格刪掉;
- 把原文中所有大寫英文字母變成小寫,除了
I
; - 把原文中所有獨立的
can you
、could you
對應地換成I can
、I could
—— 這裡“獨立”是指被空格或標點符號分隔開的單詞; - 把原文中所有獨立的
I
和me
換成you
; - 把原文中所有的問號
?
換成驚歎號!
; - 在一行中輸出替換後的句子作為 AI 的回答。
輸入格式:
輸入首先在第一行給出不超過 10 的正整數 N,隨後 N 行,每行給出一句不超過 1000 個字元的、以回車結尾的使用者的對話,對話為非空字串,僅包括字母、數字、空格、可見的半形標點符號。
輸出格式:
按題面要求輸出,每個 AI 的回答前要加上 AI:
和一個空格。
輸入樣例:
6
Hello ?
Good to chat with you
can you speak Chinese?
Really?
Could you show me 5
What Is this prime? I,don 't know
輸出樣例:
Hello ?
AI: hello!
Good to chat with you
AI: good to chat with you
can you speak Chinese?
AI: I can speak chinese!
Really?
AI: really!
Could you show me 5
AI: I could show you 5
What Is this prime? I,don 't know
AI: what Is this prime! you,don't know
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,front,end,len;
cin>>n;
getchar();
while(n--)
{
front=0;end=0;len=0;
string s,ans;
getline(cin,s);
cout<<s<<endl<<"AI: ";
for(int i=0;i<s.size();i++)
if(s[i]!=' '){front=i;break;}
for(int i=s.size()-1;i>=0;i--)
if(s[i]!=' '){end=i;break;}
for(int i=front;i<=end;i++)
{
if(s[i]=='?')s[i]='!';
if(s[i]>='A'&&s[i]<='Z'&&s[i]!='I')s[i]+=32;
if((s[i]==' '&&s[i+1]>='A'&&s[i+1]<='Z')||(s[i]==' '&&s[i+1]>='a'&&s[i+1]<='z')||(s[i]==' '&&s[i+1]>='0'&&s[i+1]<='9')||(s[i]!=' '))
{ans+=s[i];len++;}
}
for(int i=0;i<len;i++)
{
if((!isalpha(ans[i-1])&&!isdigit(ans[i-1])&&ans[i]=='I'&&!isalpha(ans[i+1])&&!isdigit(ans[i+1]))||(i==0&&ans[i]=='I'&&!isalpha(ans[i+1])&&!isdigit(ans[i+1]))||(!isdigit(ans[i-1])&&!isalpha(ans[i-1])&&ans[i]=='I'&&i==(len-1))||(i==(len-1)&&i==0&&ans[i]=='I'))cout<<"you";
else if((!isdigit(ans[i-1])&&!isalpha(ans[i-1])&&ans[i]=='m'&&!isalpha(ans[i+2])&&!isdigit(ans[i+2])&&ans[i+1]=='e')||(i==0&&ans[i]=='m'&&!isalpha(ans[i+2])&&!isdigit(ans[i+2])&&ans[i+1]=='e')||(!isdigit(ans[i-1])&&!isalpha(ans[i-1])&&ans[i]=='m'&&ans[i+1]=='e'&&(i+1)==(len-1))||(ans[i]=='m'&&ans[i+1]=='e'&&i==0&&(i+1)==(len-1))){cout<<"you";i++;}
else if((i==0&&ans[i]=='c'&&ans[i+1]=='a'&&ans[i+2]=='n'&&!isalpha(ans[i+3])&&!isdigit(ans[i+3])&&ans[i+4]=='y'&&ans[i+5]=='o'&&ans[i+6]=='u'&&(i+6)==(len-1))||(i==0&&ans[i]=='c'&&ans[i+1]=='a'&&ans[i+2]=='n'&&!isalpha(ans[i+3])&&!isdigit(ans[i+3])&&ans[i+4]=='y'&&ans[i+5]=='o'&&ans[i+6]=='u'&&!isdigit(ans[i+7])&&!isalpha(ans[i+7]))||(!isdigit(ans[i-1])&&!isalpha(ans[i-1])&&ans[i]=='c'&&ans[i+1]=='a'&&ans[i+2]=='n'&&!isalpha(ans[i+3])&&!isdigit(ans[i+3])&&ans[i+4]=='y'&&ans[i+5]=='o'&&ans[i+6]=='u'&&!isalpha(ans[i+7])&&!isdigit(ans[i+7]))||(!isdigit(ans[i-1])&&!isalpha(ans[i-1])&&ans[i]=='c'&&ans[i+1]=='a'&&ans[i+2]=='n'&&!isdigit(ans[i+3])&&!isalpha(ans[i+3])&&ans[i+4]=='y'&&ans[i+5]=='o'&&ans[i+6]=='u'&&(i+6)==(len-1))){cout<<"I"<<ans[i+3]<<"can";i+=6;}
else if((i==0&&ans[i]=='c'&&ans[i+1]=='o'&&ans[i+2]=='u'&&ans[i+3]=='l'&&ans[i+4]=='d'&&!isalpha(ans[i+5])&&!isdigit(ans[i+5])&&ans[i+6]=='y'&&ans[i+7]=='o'&&ans[i+8]=='u'&&(i+8)==(len-1))||(i==0&&ans[i]=='c'&&ans[i+1]=='o'&&ans[i+2]=='u'&&ans[i+3]=='l'&&ans[i+4]=='d'&&!isalpha(ans[i+5])&&!isdigit(ans[i+5])&&ans[i+6]=='y'&&ans[i+7]=='o'&&ans[i+8]=='u'&&!isalpha(ans[i+9])&&!isdigit(ans[i+9]))||(!isdigit(ans[i-1])&&!isalpha(ans[i-1])&&ans[i]=='c'&&ans[i+1]=='o'&&ans[i+2]=='u'&&ans[i+3]=='l'&&ans[i+4]=='d'&&!isalpha(ans[i+5])&&!isdigit(ans[i+5])&&ans[i+6]=='y'&&ans[i+7]=='o'&&ans[i+8]=='u'&&!isalpha(ans[i+9])&&!isdigit(ans[i+9]))||(!isdigit(ans[i-1])&&!isalpha(ans[i-1])&&ans[i]=='c'&&ans[i+1]=='o'&&ans[i+2]=='u'&&ans[i+3]=='l'&&ans[i+4]=='d'&&!isalpha(ans[i+5])&&!isdigit(ans[i+5])&&ans[i+6]=='y'&&ans[i+7]=='o'&&ans[i+8]=='u'&&(i+8)==(len-1))){cout<<"I"<<ans[i+5]<<"could";i+=8;}
else cout<<ans[i];
}
cout<<endl;
}
return 0;
}
7-10 特立獨行的幸福 (25分)
對一個十進位制數的各位數字做一次平方和,稱作一次迭代。如果一個十進位制數能通過若干次迭代得到 1,就稱該數為幸福數。1 是一個幸福數。此外,例如 19 經過 1 次迭代得到 82,2 次迭代後得到 68,3 次迭代後得到 100,最後得到 1。則 19 就是幸福數。顯然,在一個幸福數迭代到 1 的過程中經過的數字都是幸福數,它們的幸福是依附於初始數字的。例如 82、68、100 的幸福是依附於 19 的。而一個特立獨行的幸福數,是在一個有限的區間內不依附於任何其它數字的;其獨立性就是依附於它的的幸福數的個數。如果這個數還是個素數,則其獨立性加倍。例如 19 在區間[1, 100] 內就是一個特立獨行的幸福數,其獨立性為 2×4=8。
另一方面,如果一個大於1的數字經過數次迭代後進入了死迴圈,那這個數就不幸福。例如 29 迭代得到 85、89、145、42、20、4、16、37、58、89、…… 可見 89 到 58 形成了死迴圈,所以 29 就不幸福。
本題就要求你編寫程式,列出給定區間內的所有特立獨行的幸福數和它的獨立性。
輸入格式:
輸入在第一行給出閉區間的兩個端點:1<A<B≤104。
輸出格式:
按遞增順序列出給定閉區間 [A,B] 內的所有特立獨行的幸福數和它的獨立性。每對數字佔一行,數字間以 1 個空格分隔。
如果區間內沒有幸福數,則在一行中輸出 SAD
。
輸入樣例 1:
10 40
輸出樣例 1:
19 8
23 6
28 3
31 4
32 3
注意:樣例中,10、13 也都是幸福數,但它們分別依附於其他數字(如 23、31 等等),所以不輸出。其它數字雖然其實也依附於其它幸福數,但因為那些數字不在給定區間 [10, 40] 內,所以它們在給定區間內是特立獨行的幸福數。
輸入樣例 2:
110 120
輸出樣例 2:
SAD
7-11 冰島人 (25分)
2018年世界盃,冰島隊因1:1平了強大的阿根廷隊而一戰成名。好事者發現冰島人的名字後面似乎都有個“鬆”(son),於是有網友科普如下:
冰島人沿用的是維京人古老的父系姓制,孩子的姓等於父親的名加字尾,如果是兒子就加 sson,女兒則加 sdottir。因為冰島人口較少,為避免近親繁衍,本地人交往前先用個 App 查一下兩人祖宗若干代有無聯絡。本題就請你實現這個 App 的功能。
輸入格式:
輸入首先在第一行給出一個正整數 N(1<N≤105),為當地人口數。隨後 N 行,每行給出一個人名,格式為:名 姓(帶性別字尾)
,兩個字串均由不超過 20 個小寫的英文字母組成。維京人後裔是可以通過姓的字尾判斷其性別的,其他人則是在姓的後面加 m
表示男性、f
表示女性。題目保證給出的每個維京家族的起源人都是男性。
隨後一行給出正整數 M,為查詢數量。隨後 M 行,每行給出一對人名,格式為:名1 姓1 名2 姓2
。注意:這裡的姓
是不帶字尾的。四個字串均由不超過 20 個小寫的英文字母組成。
題目保證不存在兩個人是同名的。
輸出格式:
對每一個查詢,根據結果在一行內顯示以下資訊:
- 若兩人為異性,且五代以內無公共祖先,則輸出
Yes
; - 若兩人為異性,但五代以內(不包括第五代)有公共祖先,則輸出
No
; - 若兩人為同性,則輸出
Whatever
; - 若有一人不在名單內,則輸出
NA
。
所謂“五代以內無公共祖先”是指兩人的公共祖先(如果存在的話)必須比任何一方的曾祖父輩分高。
輸入樣例:
15
chris smithm
adam smithm
bob adamsson
jack chrissson
bill chrissson
mike jacksson
steve billsson
tim mikesson
april mikesdottir
eric stevesson
tracy timsdottir
james ericsson
patrick jacksson
robin patricksson
will robinsson
6
tracy tim james eric
will robin tracy tim
april mike steve bill
bob adam eric steve
tracy tim tracy tim
x man april mikes
輸出樣例:
Yes
No
No
Whatever
Whatever
NA
7-12 深入虎穴 (25分)
著名的王牌間諜 007 需要執行一次任務,獲取敵方的機密情報。已知情報藏在一個地下迷宮裡,迷宮只有一個入口,裡面有很多條通路,每條路通向一扇門。每一扇門背後或者是一個房間,或者又有很多條路,同樣是每條路通向一扇門…… 他的手裡有一張表格,是其他間諜幫他收集到的情報,他們記下了每扇門的編號,以及這扇門背後的每一條通路所到達的門的編號。007 發現不存在兩條路通向同一扇門。
內線告訴他,情報就藏在迷宮的最深處。但是這個迷宮太大了,他需要你的幫助 —— 請程式設計幫他找出距離入口最遠的那扇門。
輸入格式:
輸入首先在一行中給出正整數 N(<105),是門的數量。最後 N 行,第 i 行(1≤i≤N)按以下格式描述編號為 i 的那扇門背後能通向的門:
K D[1] D[2] ... D[K]
其中 K
是通道的數量,其後是每扇門的編號。
輸出格式:
在一行中輸出距離入口最遠的那扇門的編號。題目保證這樣的結果是唯一的。
輸入樣例:
13
3 2 3 4
2 5 6
1 7
1 8
1 9
0
2 11 10
1 13
0
0
1 12
0
0
輸出樣例:
12
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int d[maxn];
stack<int> ko;
int main()
{
int n,k,x,ans,p=1,cnt,temp;
cin>>n;
memset(d,0,sizeof(d));
for(int i=1;i<=n;i++)
{
cin>>k;
if(k!=0)for(int j=1;j<=k;j++){scanf("%d",&x);d[x]=i;}
else ko.push(i);//將每個結束點儲存
}//讀入完畢
ans=ko.top();
while(ko.size())//從每個結束點倒回去找
{
temp=ko.top();cnt=0;
while(d[temp]!=0){temp=d[temp];cnt++;}//計算深度
if(cnt>p){p=cnt; ans=ko.top();}//記錄最深的
ko.pop();
}
cout<<ans;
return 0;
}
7-13 彩虹瓶 (25分)
彩虹瓶的製作過程(並不)是這樣的:先把一大批空瓶鋪放在裝填場地上,然後按照一定的順序將每種顏色的小球均勻撒到這批瓶子裡。
假設彩虹瓶裡要按順序裝 N 種顏色的小球(不妨將順序就編號為 1 到 N)。現在工廠裡有每種顏色的小球各一箱,工人需要一箱一箱地將小球從工廠裡搬到裝填場地。如果搬來的這箱小球正好是可以裝填的顏色,就直接拆箱裝填;如果不是,就把箱子先碼放在一個臨時貨架上,碼放的方法就是一箱一箱堆上去。當一種顏色裝填完以後,先看看貨架頂端的一箱是不是下一個要裝填的顏色,如果是就取下來裝填,否則去工廠裡再搬一箱過來。
如果工廠裡發貨的順序比較好,工人就可以順利地完成裝填。例如要按順序裝填 7 種顏色,工廠按照 7、6、1、3、2、5、4 這個順序發貨,則工人先拿到 7、6 兩種不能裝填的顏色,將其按照 7 在下、6 在上的順序堆在貨架上;拿到 1 時可以直接裝填;拿到 3 時又得臨時碼放在 6 號顏色箱上;拿到 2 時可以直接裝填;隨後從貨架頂取下 3 進行裝填;然後拿到 5,臨時碼放到 6 上面;最後取了 4 號顏色直接裝填;剩下的工作就是順序從貨架上取下 5、6、7 依次裝填。
但如果工廠按照 3、1、5、4、2、6、7 這個順序發貨,工人就必須要憤怒地折騰貨架了,因為裝填完 2 號顏色以後,不把貨架上的多個箱子搬下來就拿不到 3 號箱,就不可能順利完成任務。
另外,貨架的容量有限,如果要堆積的貨物超過容量,工人也沒辦法順利完成任務。例如工廠按照 7、6、5、4、3、2、1 這個順序發貨,如果貨架夠高,能碼放 6 只箱子,那還是可以順利完工的;但如果貨架只能碼放 5 只箱子,工人就又要憤怒了……
本題就請你判斷一下,工廠的發貨順序能否讓工人順利完成任務。
輸入格式:
輸入首先在第一行給出 3 個正整數,分別是彩虹瓶的顏色數量 N(1<N≤103)、臨時貨架的容量 M(<N)、以及需要判斷的發貨順序的數量 K。
隨後 K 行,每行給出 N 個數字,是 1 到N 的一個排列,對應工廠的發貨順序。
一行中的數字都以空格分隔。
輸出格式:
對每個發貨順序,如果工人可以愉快完工,就在一行中輸出 YES
;否則輸出 NO
。
輸入樣例:
7 5 3
7 6 1 3 2 5 4
3 1 5 4 2 6 7
7 6 5 4 3 2 1
輸出樣例:
YES
NO
NO
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,m,k,x,cnt,flag;
cin>>n>>m>>k;
while(k--)
{
stack<int>a;
cnt=1;flag=1;
for(int i=0;i<n;i++)
{
cin>>x;
if(x==cnt)
{
cnt++;
while(a.size())
{
if(a.top()==cnt){a.pop();cnt++;}
else break;
}
}
else{a.push(x);if(a.size()>m) flag=0;}
}
if(a.size()==0&&flag==1) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
7-14 Oriol和David (30分)
Oriol 和 David 在一個邊長為 16 單位長度的正方形區域內,初始位置分別為(7, 7)和(8, 8)。現在有 20 組、每組包含 20 個位置需要他們訪問,位置以座標(x, y)的形式給出,要求在時間 120 秒內訪問儘可能多的點。(x和y均為正整數,且0 ≤ x < 16,0 ≤ y < 16)
注意事項:
- 針對任意一個位置,Oriol或David中的一人到達即視為訪問成功;
- Oriol和David必須從第 1 組位置開始訪問,且必須訪問完第 i 組全部20個位置之後,才可以開始第 i + 1 組 20 個位置的訪問。同組間各位置的訪問順序可自由決定;
- Oriol和David在完成當前組位置的訪問後,無需返回開始位置、可以立即開始下一組位置的訪問;
- Oriol和David可以向任意方向移動,移動時速率為 2 單位長度/秒;移動過程中,無任何障礙物阻攔。
輸入格式:
輸入第一行是一個正整數 T (T ≤ 10),表示資料組數。接下來給出 T 組資料。
對於每組資料,輸入包含 20 組,每組 1 行,每行由 20 個座標組成,每個座標由 2 個整數 x 和 y 組成,代表 Oriol 和 David 要訪問的 20 組 20 個位置的座標;0 ≤ x < 16,0 ≤ y < 16,均用一個空格隔開。
輸出格式:
每組資料輸出的第一行是一個整數N,代表分配方案訪問過的位置組數;
接下來的N組每組的第一行包含兩個整數 Ba 和 Bb,分別代表每組分配方案中 Oriol 和 David 負責訪問的位置數,第二行和第三行分別包含 Ba 和 Bb 個整數 i,分別代表 Oriol 和 David 負責訪問的位置在組內的序號(從0開始計數)。
0 ≤ N ≤ 20,0 ≤ Ba ≤ 20,0 ≤ Bb ≤ 20,0 ≤ i ≤ 19。
輸入樣例:
1
5 5 3 13 8 7 13 6 6 11 2 0 1 14 9 15 8 9 3 12 4 6 2 10 2 5 4 9 4 1 15 0 11 4 10 0 15 5 10 14
1 0 14 8 0 7 6 8 4 12 12 8 9 8 10 14 9 4 13 4 9 1 2 1 0 2 11 10 7 15 9 6 13 11 3 5 4 5 10 7
7 3 8 13 15 0 5 4 2 8 7 14 4 13 11 1 8 15 4 5 4 7 7 10 6 7 13 4 6 2 9 13 1 12 10 7 10 5 5 11
5 8 12 12 11 5 12 9 2 2 11 15 5 14 0 0 14 0 2 5 7 3 10 1 2 8 4 2 4 8 9 14 1 11 1 9 15 7 3 3
1 9 10 14 7 3 15 5 5 15 3 2 12 11 8 10 3 3 11 5 7 4 6 11 6 1 4 10 11 13 12 4 3 4 1 3 7 5 13 11
3 11 9 8 12 9 14 10 11 13 5 5 4 11 1 12 13 2 10 14 5 15 10 15 11 0 3 6 7 11 4 9 15 0 12 14 10 10 13 11
10 4 9 12 0 13 6 6 7 10 11 15 6 14 1 2 4 9 8 5 4 0 13 11 5 3 13 3 9 8 2 4 13 14 12 12 14 2 8 15
2 8 4 9 13 10 8 5 2 13 12 6 4 4 10 6 14 13 11 5 12 1 6 0 11 2 8 15 12 4 13 8 8 2 9 7 7 13 0 9
0 0 4 0 2 3 10 2 7 3 9 4 2 13 11 11 1 8 11 15 11 2 8 11 10 15 7 9 13 15 15 10 1 2 11 9 14 6 5 5
2 13 6 8 7 14 8 5 15 14 5 6 4 10 14 12 3 14 0 5 4 1 0 14 13 14 12 5 5 9 1 2 2 12 4 8 1 15 7 11
10 5 15 7 6 8 11 10 7 13 14 0 12 2 9 12 4 5 3 8 8 13 7 12 15 15 12 9 15 6 14 3 9 6 15 12 7 9 4 15
0 10 6 2 3 2 6 3 14 6 10 13 3 10 15 9 10 0 7 0 14 15 1 2 13 9 11 11 10 3 6 13 0 14 11 2 9 8 15 5
3 9 13 11 1 1 0 9 5 4 4 9 4 13 10 1 12 11 4 2 0 4 1 7 4 10 4 0 2 1 2 0 13 2 11 10 0 5 15 3
15 11 8 1 12 5 8 5 7 5 7 7 2 4 0 4 7 3 12 6 9 15 5 12 14 11 15 10 8 11 4 10 4 14 13 10 4 4 2 12
9 12 15 13 0 12 0 14 3 1 10 15 15 11 1 12 3 0 5 2 15 10 8 4 9 1 8 0 1 13 2 7 12 13 14 10 6 0 13 15
13 7 14 15 9 4 8 2 7 3 7 11 2 13 5 0 13 5 4 0 12 2 3 2 11 15 9 2 9 7 3 7 4 5 14 5 14 12 9 13
12 11 2 14 2 6 6 12 5 15 13 11 2 0 9 13 7 1 7 11 4 4 2 10 0 8 5 3 6 13 2 7 2 15 6 8 3 5 8 11
12 5 9 9 4 14 3 2 14 2 2 1 9 11 8 10 2 14 12 15 0 13 4 7 0 0 0 6 0 1 4 13 4 3 3 10 15 2 10 10
11 15 8 5 6 15 9 8 2 7 15 14 1 10 14 6 13 6 0 15 4 1 3 12 7 8 12 4 0 10 7 10 0 14 13 5 11 1 15 6
1 12 13 14 6 12 9 0 6 8 3 15 5 4 4 2 15 10 3 6 13 12 8 4 15 3 1 5 7 1 6 14 8 6 2 6 11 3 4 4
輸出樣例:
2
10 10
1 2 3 4 5 6 7 8 9 0
11 12 13 14 15 16 17 18 19 10
1 19
1
0 2 3 4 5 6 7 8 9 11 12 13 14 15 16 17 18 19 10
注意:樣例只代表格式,不具有特別含義。
評分方式:
本題按照你給出的方案的優良程度評定分數。
具體評分規則如下:
- 本題所有資料點輸入均為一樣的資料;
- 評分時,假定輸入有 X 組資料,則你的評分答案為你的程式在所有 X 組資料中答案的平均值;
- 例如,你對 3 組資料,分別訪問了 3 個、5 個、8 個點,則你的評分答案為 5.33333...
- 特別的,如果你輸出的答案中有任意一組不合法,則你的評分答案恆定為 0;
- 輸出方案行走超過 120 秒仍然合法,答案計算時只計算 120 秒內的部分;
- 評測時,從 0 開始的測試點的標準答案依次增大,只有評分答案超過標準答案時,你才可以得到對應測試點的分數。
不合法的情況如下:
- 輸出格式不正確;
- 重複訪問自己已訪問的點;(但可以經過)
- 訪問不存在的點。
部分評分標準答案如下:
- 第 0 號點:20;(即需要訪問平均 20 個點才可以獲得該點分數)
- 第 1 號點:70;(同上)
- 第 2 號點:90;
- 第 7 號點:150。
7-15 計算圖 (30分)
“計算圖”(computational graph)是現代深度學習系統的基礎執行引擎,提供了一種表示任意數學表示式的方法,例如用有向無環圖表示的神經網路。 圖中的節點表示基本操作或輸入變數,邊表示節點之間的中間值的依賴性。 例如,下圖就是一個函式 f(x1,x2)=lnx1+x1x2−sinx2 的計算圖。
現在給定一個計算圖,請你根據所有輸入變數計算函式值及其偏導數(即梯度)。 例如,給定輸入x1=2,x2=5,上述計算圖獲得函式值 f(2,5)=ln(2)+2×5−sin(5)=11.652;並且根據微分鏈式法則,上圖得到的梯度 ∇f=[∂f/∂x1,∂f/∂x2]=[1/x1+x2,x1−cosx2]=[5.500,1.716]。
知道你已經把微積分忘了,所以這裡只要求你處理幾個簡單的運算元:加法、減法、乘法、指數(e**x,即程式語言中的 exp(x) 函式)、對數(lnx,即程式語言中的 log(x) 函式)和正弦函式(sinx,即程式語言中的 sin(x) 函式)。
友情提醒:
- 常數的導數是 0;x 的導數是 1;e**x 的導數還是 e**x;lnx 的導數是 1/x;sinx 的導數是 cosx。
- 回顧一下什麼是偏導數:在數學中,一個多變數的函式的偏導數,就是它關於其中一個變數的導數而保持其他變數恆定。在上面的例子中,當我們對 x1 求偏導數 ∂f/∂x1 時,就將 x2 當成常數,所以得到 lnx1 的導數是 1/x1,x1x2 的導數是 x2,sinx2 的導數是 0。
- 回顧一下鏈式法則:複合函式的導數是構成複合這有限個函式在相應點的導數的乘積,即若有 u=f(y),y=g(x),則 d**u/d**x=d**u/d**y⋅d**y/d**x。例如對 sin(lnx) 求導,就得到 cos(lnx)⋅(1/x)。
如果你注意觀察,可以發現在計算圖中,計算函式值是一個從左向右進行的計算,而計算偏導數則正好相反。
輸入格式:
輸入在第一行給出正整數 N(≤5×104),為計算圖中的頂點數。
以下 N 行,第 i 行給出第 i 個頂點的資訊,其中 i=0,1,⋯,N−1。第一個值是頂點的型別編號,分別為:
- 0 代表輸入變數
- 1 代表加法,對應 x1+x2
- 2 代表減法,對應 x1−x2
- 3 代表乘法,對應 x1×x2
- 4 代表指數,對應 e**x
- 5 代表對數,對應 lnx
- 6 代表正弦函式,對應 sinx
對於輸入變數,後面會跟它的雙精度浮點數值;對於單目運算元,後面會跟它對應的單個變數的頂點編號(編號從 0 開始);對於雙目運算元,後面會跟它對應兩個變數的頂點編號。
題目保證只有一個輸出頂點(即沒有出邊的頂點,例如上圖最右邊的 -
),且計算過程不會超過雙精度浮點數的計算精度範圍。
輸出格式:
首先在第一行輸出給定計算圖的函式值。在第二行順序輸出函式對於每個變數的偏導數的值,其間以一個空格分隔,行首尾不得有多餘空格。偏導數的輸出順序與輸入變數的出現順序相同。輸出小數點後 3 位。
輸入樣例:
7
0 2.0
0 5.0
5 0
3 0 1
6 1
1 2 3
2 5 4
輸出樣例:
11.652
5.500 1.716