1. 程式人生 > 實用技巧 >2020年HZNU天梯訓練賽 Round 2

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分)

本題要求你計算AB。不過麻煩的是,AB都是字串 —— 即從字串A中把字串B所包含的字元全刪掉,剩下的字元組成的就是字串AB

輸入格式:

輸入在2行中先後給出字串AB。兩字串的長度都不超過104,並且保證每個字串都是由可見的ASCII碼和空白字元組成,最後以換行符結束。

輸出格式:

在一行中打印出AB的結果字串。

輸入樣例:
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

其中P1P2是道路兩端點的編號,端點可以是居民點,也可以是垃圾箱候選點。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 插入堆疊,無需輸出;對每個 PopPeekMedian 操作,在一行中輸出相應的返回值。若操作非法,則對應輸出 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