2020年HZNU天梯訓練賽 Round 2
2020年HZNU天梯訓練賽 Round 2
時間:2020.7.15 27
完成情況:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
√ | √ | √ | √ | √ | √ | √ | √ | √ | ※ | |||||
√ 當場做出來 ※做了一半來 ✘補題補出來
7-1 比較大小 (10分)
本題要求將輸入的任意3個整數從小到大輸出。
輸入格式:
輸入在一行中給出3個整數,其間以空格分隔。
輸出格式:
在一行中將3個整數從小到大輸出,其間以“->”相連。
輸入樣例:
4 2 8
輸出樣例:
2->4->8
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+5; int main() { int a[3]; for(int i=0;i<3;i++) cin>>a[i]; sort(a,a+3); for(int i=0;i<2;i++) cout<<a[i]<<"->"; cout<<a[2]<<endl; return 0; }
7-2 N個數求和 (20分)
本題的要求很簡單,就是求N
個數字的和。麻煩的是,這些數字是以有理數分子/分母
的形式給出的,你輸出的和也必須是有理數的形式。
輸入格式:
輸入第一行給出一個正整數N
(≤100)。隨後一行按格式a1/b1 a2/b2 ...
給出N
個有理數。題目保證所有分子和分母都在長整型範圍內。另外,負數的符號一定出現在分子前面。
輸出格式:
輸出上述數字和的最簡形式 —— 即將結果寫成整數部分 分數部分
,其中分數部分寫成分子/分母
,要求分子小於分母,且它們沒有公因子。如果結果的整數部分為0,則只輸出分數部分。
輸入樣例1:
5
2/5 4/15 1/30 -2/60 8/3
輸出樣例1:
3 1/3
輸入樣例2:
2
4/3 2/3
輸出樣例2:
2
輸入樣例3:
3
1/3 -1/6 1/8
輸出樣例3:
7/24
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+5; typedef long long LL; LL gcd(LL a,LL b) { if(b==0) return a; return gcd(b,a%b); } int main() { LL i,j,n,a[101],b[101],x,y; scanf("%lld",&n); for(i=0;i<n;i++) scanf("%lld/%lld",&a[i],&b[i]); x=0,y=1; for(i=0;i<n;i++) { LL x1= x*b[i]+y*a[i];LL y1= y* b[i]; x=x1/gcd(x1,y1);y=y1/gcd(x1,y1); } if(x==0){printf("0\n");} else if(x%y==0){printf("%lld\n",x/y);} else if(abs(x)<y&&x%y!=0){printf("%lld/%lld\n",x,y);} else{printf("%lld %lld/%lld\n",x/y,x%y,y);} return 0; } //(abs(x)>y)
7-3 A-B (20分)
本題要求你計算A−B。不過麻煩的是,A和B都是字串 —— 即從字串A中把字串B所包含的字元全刪掉,剩下的字元組成的就是字串A−B。
輸入格式:
輸入在2行中先後給出字串A和B。兩字串的長度都不超過104,並且保證每個字串都是由可見的ASCII碼和空白字元組成,最後以換行符結束。
輸出格式:
在一行中打印出A−B的結果字串。
輸入樣例:
I love GPLT! It's a fun game!
aeiou
輸出樣例:
I lv GPLT! It's fn gm!
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int main()
{
int flag;
char a[10005],b[10005];
cin.getline(a,10005);
cin.getline(b,10005);
for(int i=0;i<strlen(a);i++)
{
flag=1;
for(int j=0;j<strlen(b);j++)
{
if(a[i]==b[j])
flag=0;
}
if(flag==1) cout<<a[i];
}
return 0;
}
7-4 計算指數 (5分)
真的沒騙你,這道才是簡單題 —— 對任意給定的不超過10的正整數n,要求你輸出2n。不難吧?
輸入格式:
輸入在一行中給出一個不超過10的正整數n。
輸出格式:
在一行中按照格式 2^n = 計算結果
輸出2n的值。
輸入樣例:
5
輸出樣例:
2^5 = 32
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int main()
{
int n;
cin>>n;
cout<<"2^"<<n<<" = "<<pow(2,n);
return 0;
}
7-5 計算階乘和 (10分)
對於給定的正整數N,需要你計算 S=1!+2!+3!+...+N!。
輸入格式:
輸入在一行中給出一個不超過10的正整數N。
輸出格式:
在一行中輸出S的值。
輸入樣例:
3
輸出樣例:
9
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int jc(int i)
{
int ans=1;
for(int j=1;j<=i;j++)
{
ans*=j;
}
return ans;
}
int main()
{
int n,sum=0;
cin>>n;
for(int i=1;i<=n;i++)
sum+=jc(i);
cout<<sum;
return 0;
}
7-6 簡單題 (5分)
這次真的沒騙你 —— 這道超級簡單的題目沒有任何輸入。
你只需要在一行中輸出事實:This is a simple problem.
就可以了。
This is a simple problem.
7-7 跟奧巴馬一起畫方塊 (15分)
美國總統奧巴馬不僅呼籲所有人都學習程式設計,甚至以身作則編寫程式碼,成為美國曆史上首位編寫計算機程式碼的總統。2014年底,為慶祝“電腦科學教育周”正式啟動,奧巴馬編寫了很簡單的計算機程式碼:在螢幕上畫一個正方形。現在你也跟他一起畫吧!
輸入格式:
輸入在一行中給出正方形邊長N(3≤N≤21)和組成正方形邊的某種字元C
,間隔一個空格。
輸出格式:
輸出由給定字元C
畫出的正方形。但是注意到行間距比列間距大,所以為了讓結果看上去更像正方形,我們輸出的行數實際上是列數的50%(四捨五入取整)。
輸入樣例:
10 a
輸出樣例:
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int main()
{
int n;
char c;
scanf("%d %c",&n,&c);
if(n%2==0)
{
for(int i=0;i<n/2;i++)
{
for(int j=0;j<n;j++)
cout<<c;
cout<<endl;
}
}
else
{
for(int i=0;i<n/2+1;i++)
{
for(int j=0;j<n;j++)
cout<<c;
cout<<endl;
}
}
return 0;
}
7-8 查驗身份證 (15分)
一個合法的身份證號碼由17位地區、日期編號和順序編號加1位校驗碼組成。校驗碼的計算規則如下:
首先對前17位數字加權求和,權重分配為:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};然後將計算的和對11取模得到值Z
;最後按照以下關係對應Z
值與校驗碼M
的值:
Z:0 1 2 3 4 5 6 7 8 9 10
M:1 0 X 9 8 7 6 5 4 3 2
現在給定一些身份證號碼,請你驗證校驗碼的有效性,並輸出有問題的號碼。
輸入格式:
輸入第一行給出正整數N(≤100)是輸入的身份證號碼的個數。隨後N行,每行給出1個18位身份證號碼。
輸出格式:
按照輸入的順序每行輸出1個有問題的身份證號碼。這裡並不檢驗前17位是否合理,只檢查前17位是否全為數字且最後1位校驗碼計算準確。如果所有號碼都正常,則輸出All passed
。
輸入樣例1:
4
320124198808240056
12010X198901011234
110108196711301866
37070419881216001X
輸出樣例1:
12010X198901011234
110108196711301866
37070419881216001X
輸入樣例2:
2
320124198808240056
110108196711301862
輸出樣例2:
All passed
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int a[17]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
char M[15]={'1','0','X','9','8','7','6','5','4','3','2'};
int main()
{
int t,flag=1;
cin>>t;
while(t--)
{
char f[18];
int sum=0,z;
cin>>f;
for(int i=0;i<17;i++)
sum+=a[i]*(f[i]-'0');
z=sum%11;
if(f[17]!=M[z])
{
flag=0;
cout<<f<<endl;
}
}
if(flag==1)cout<<"All passed"<<endl;
return 0;
}
7-9 集合相似度 (25分)
給定兩個整數集合,它們的相似度定義為:N**c/N**t×100%。其中N**c是兩個集合都有的不相等整數的個數,N**t是兩個集合一共有的不相等整數的個數。你的任務就是計算任意一對給定集合的相似度。
輸入格式:
輸入第一行給出一個正整數N(≤50),是集合的個數。隨後N行,每行對應一個集合。每個集合首先給出一個正整數M(≤104),是集合中元素的個數;然後跟M個[0,109]區間內的整數。
之後一行給出一個正整數K(≤2000),隨後K行,每行對應一對需要計算相似度的集合的編號(集合從1到N編號)。數字間以空格分隔。
輸出格式:
對每一對需要計算的集合,在一行中輸出它們的相似度,為保留小數點後2位的百分比數字。
輸入樣例:
3
3 99 87 101
4 87 101 5 87
7 99 101 18 5 135 18 99
2
1 2
1 3
輸出樣例:
50.00%
33.33%
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
typedef long long LL;
set<int>s[52];
int main()
{
set<int>::iterator it;
int n,m,t,x,y,z;
double x1,x2,ans;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>m;
while(m--){cin>>x;s[i].insert(x);}
}
cin>>t;
while(t--)
{
x1=0,x2=0;
cin>>y>>z;
for(it=s[y].begin();it!=s[y].end();it++)
{
if(s[z].find(*it)!=s[z].end()) x1+=1;
else x2+=1;
}
ans=x1/(x2+s[z].size())*100;
printf("%.2lf%%\n",ans);
}
return 0;
}
7-10 樹的遍歷 (25分)
給定一棵二叉樹的後序遍歷和中序遍歷,請你輸出其層序遍歷的序列。這裡假設鍵值都是互不相等的正整數。
輸入格式:
輸入第一行給出一個正整數N(≤30),是二叉樹中結點的個數。第二行給出其後序遍歷序列。第三行給出其中序遍歷序列。數字間以空格分隔。
輸出格式:
在一行中輸出該樹的層序遍歷的序列。數字間以1個空格分隔,行首尾不得有多餘空格。
輸入樣例:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
輸出樣例:
4 1 6 3 5 7 2
7-11 家庭房產 (25分)
給定每個人的家庭成員和其自己名下的房產,請你統計出每個家庭的人口數、人均房產面積及房產套數。
輸入格式:
輸入第一行給出一個正整數N(≤1000),隨後N行,每行按下列格式給出一個人的房產:
編號 父 母 k 孩子1 ... 孩子k 房產套數 總面積
其中編號
是每個人獨有的一個4位數的編號;父
和母
分別是該編號對應的這個人的父母的編號(如果已經過世,則顯示-1
);k
(0≤k
≤5)是該人的子女的個數;孩子i
是其子女的編號。
輸出格式:
首先在第一行輸出家庭個數(所有有親屬關係的人都屬於同一個家庭)。隨後按下列格式輸出每個家庭的資訊:
家庭成員的最小編號 家庭人口數 人均房產套數 人均房產面積
其中人均值要求保留小數點後3位。家庭資訊首先按人均面積降序輸出,若有並列,則按成員編號的升序輸出。
輸入樣例:
10
6666 5551 5552 1 7777 1 100
1234 5678 9012 1 0002 2 300
8888 -1 -1 0 1 1000
2468 0001 0004 1 2222 1 500
7777 6666 -1 0 2 300
3721 -1 -1 1 2333 2 150
9012 -1 -1 3 1236 1235 1234 1 100
1235 5678 9012 0 1 50
2222 1236 2468 2 6661 6662 1 300
2333 -1 3721 3 6661 6662 6663 1 100
輸出樣例:
3
8888 1 1.000 1000.000
0001 15 0.600 100.000
5551 4 0.750 100.000
7-12 最長對稱子串 (25分)
對給定的字串,本題要求你輸出最長對稱子串的長度。例如,給定Is PAT&TAP symmetric?
,最長對稱子串為s PAT&TAP s
,於是你應該輸出11。
輸入格式:
輸入在一行中給出長度不超過1000的非空字串。
輸出格式:
在一行中輸出最長對稱子串的長度。
輸入樣例:
Is PAT&TAP symmetric?
輸出樣例:
11
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
typedef long long LL;
int main(){
char s[1005];
int ans=1,cnt,temp;
cin.getline(s,10005);
for(int i=0;i<strlen(s);i++)//正序
{
cnt=1,temp=i;
//cout>>k;
for(int j=strlen(s)-1;j>i;j--)//倒序
{
if(s[temp]==s[j])//
{
if(temp+1==j)//中間部分為T&T
{
if(ans<=cnt*2)ans=cnt*2;break;
}
if(temp==j)//中間部分為T&&T
{
if(ans<=cnt*2-1)ans=cnt*2-1;break;
}
if(s[temp+1]==s[j-1]){cnt++;temp++;}//不斷靠近
else cnt=1;
}
}
}
cout<<ans<<endl;
return 0;
}
7-13 垃圾箱分佈 (30分)
大家倒垃圾的時候,都希望垃圾箱距離自己比較近,但是誰都不願意守著垃圾箱住。所以垃圾箱的位置必須選在到所有居民點的最短距離最長的地方,同時還要保證每個居民點都在距離它一個不太遠的範圍內。
現給定一個居民區的地圖,以及若干垃圾箱的候選地點,請你推薦最合適的地點。如果解不唯一,則輸出到所有居民點的平均距離最短的那個解。如果這樣的解還是不唯一,則輸出編號最小的地點。
輸入格式:
輸入第一行給出4個正整數:N(≤103)是居民點的個數;M(≤10)是垃圾箱候選地點的個數;K(≤104)是居民點和垃圾箱候選地點之間的道路的條數;D**S是居民點與垃圾箱之間不能超過的最大距離。所有的居民點從1到N編號,所有的垃圾箱候選地點從G1到G**M編號。
隨後K行,每行按下列格式描述一條道路:
P1 P2 Dist
其中P1
和P2
是道路兩端點的編號,端點可以是居民點,也可以是垃圾箱候選點。Dist
是道路的長度,是一個正整數。
輸出格式:
首先在第一行輸出最佳候選地點的編號。然後在第二行輸出該地點到所有居民點的最小距離和平均距離。數字間以空格分隔,保留小數點後1位。如果解不存在,則輸出No Solution
。
輸入樣例1:
4 3 11 5
1 2 2
1 4 2
1 G1 4
1 G2 3
2 3 2
2 G2 1
3 4 2
3 G3 2
4 G1 3
G2 G1 1
G3 G2 2
輸出樣例1:
G1
2.0 3.3
輸入樣例2:
2 1 2 10
1 G1 9
2 G1 20
輸出樣例2:
No Solution
7-14 迎風一刀斬 (30分)
迎著一面矩形的大旗一刀斬下,如果你的刀夠快的話,這筆直一刀可以切出兩塊多邊形的殘片。反過來說,如果有人拿著兩塊殘片來吹牛,說這是自己迎風一刀斬落的,你能檢查一下這是不是真的嗎?
注意擺在你面前的兩個多邊形可不一定是端端正正擺好的,它們可能被平移、被旋轉(逆時針90度、180度、或270度),或者被(映象)翻面。
這裡假設原始大旗的四邊都與座標軸是平行的。
輸入格式:
輸入第一行給出一個正整數N(≤20),隨後給出N對多邊形。每個多邊形按下列格式給出:
k**x1y1⋯xky**k
其中k(2<k≤10)是多邊形頂點個數;(x**i,y**i)(0≤x**i,y**i≤108)是頂點座標,按照順時針或逆時針的順序給出。
注意:題目保證沒有多餘頂點。即每個多邊形的頂點都是不重複的,任意3個相鄰頂點不共線。
輸出格式:
對每一對多邊形,輸出YES
或者NO
。
輸入樣例:
8
3 0 0 1 0 1 1
3 0 0 1 1 0 1
3 0 0 1 0 1 1
3 0 0 1 1 0 2
4 0 4 1 4 1 0 0 0
4 4 0 4 1 0 1 0 0
3 0 0 1 1 0 1
4 2 3 1 4 1 7 2 7
5 10 10 10 12 12 12 14 11 14 10
3 28 35 29 35 29 37
3 7 9 8 11 8 9
5 87 26 92 26 92 23 90 22 87 22
5 0 0 2 0 1 1 1 2 0 2
4 0 0 1 1 2 1 2 0
4 0 0 0 1 1 1 2 0
4 0 0 0 1 1 1 2 0
輸出樣例:
YES
NO
YES
YES
YES
YES
NO
YES
7-15 特殊堆疊 (30分)
堆疊是一種經典的後進先出的線性結構,相關的操作主要有“入棧”(在堆疊頂插入一個元素)和“出棧”(將棧頂元素返回並從堆疊中刪除)。本題要求你實現另一個附加的操作:“取中值”——即返回所有堆疊中元素鍵值的中值。給定 N 個元素,如果 N 是偶數,則中值定義為第 N/2 小元;若是奇數,則為第 (N+1)/2 小元。
輸入格式:
輸入的第一行是正整數 N(≤105)。隨後 N 行,每行給出一句指令,為以下 3 種之一:
Push key
Pop
PeekMedian
其中 key
是不超過 105 的正整數;Push
表示“入棧”;Pop
表示“出棧”;PeekMedian
表示“取中值”。
輸出格式:
對每個 Push
操作,將 key
插入堆疊,無需輸出;對每個 Pop
或 PeekMedian
操作,在一行中輸出相應的返回值。若操作非法,則對應輸出 Invalid
。
輸入樣例:
17
Pop
PeekMedian
Push 3
PeekMedian
Push 2
PeekMedian
Push 1
PeekMedian
Pop
Pop
Push 5
Push 4
PeekMedian
Pop
Pop
Pop
Pop
輸出樣例:
Invalid
Invalid
3
2
2
1
2
4
4
5
3
Invalid
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
typedef long long LL;
int n,a[10005]={0},b[10005]={0},cnt=0;
char op[10];
int main()
{
cin>>n;
while(n--)
{
memset(op,'\0',sizeof(op));
cin>>op;
if(op[0]=='P'&&op[1]=='u')
{
cin>>a[cnt];
//sort(a,a+cnt);
b[cnt]=a[cnt];
cnt++;
sort(b,b+cnt);
/*for(int i=0;i<cnt;++i)
cout<<b[i]<<"***";
cout<<endl;*/
}
if(op[0]=='P'&&op[1]=='o')
{
if(cnt<=0){cout<<"Invalid"<<endl;}
else
{ cout<<a[cnt-1]<<endl;
for(int i=0;i<cnt;++i)
{
if(b[i]==a[cnt-1])
{
for(int j=i;j<cnt-1;j++)
b[j]=b[j+1];
}
}
a[cnt-1]=0;cnt--;
}
}
if(op[0]=='P'&&op[1]=='e')
{
if(cnt<=0){cout<<"Invalid"<<endl;}
else if((cnt)%2==0)cout<<b[(cnt-1)/2]<<endl;
else cout<<b[(cnt-1+1)/2]<<endl;
}
}
return 0;
}
等待更新ing