2024寒假集训 进阶训练赛 (四)

目录

问题 A: 字符环

问题 B: 字符串最大跨距

问题 C: 读入未知数目的string对象

问题 D: 连续出现的字符

问题 E: 计算矩阵边缘元素之和

问题 F: 图像旋转

问题 G: 【蓝桥杯2022初赛】统计子矩阵

问题 H: 【蓝桥杯2022初赛】修建灌木

问题 I: 求和

问题 J: 等于没有比

问题 K: 补题抄题解

问题 L: 毛遂自荐2

问题 M: Bob和Alice(4)

问题 N: Bob和Alice(5)

问题 O: Bob和Alice(6)

问题 P: Monster Hunter

注:N-P没写代码(不会),把题目放上来了 


问题 A: 字符环

题目描述

有两个由字符构成的环。请写一个程序,计算这两个字符环上最长连续公共字符串的长度。
例如,字符串“ABCEFAGADEGKABUVKLM”的首尾连在一起,构成一个环;
字符串“MADJKLUVKL”的首尾连在一起,构成一个另一个环;
“UVKLMA”是这两个环的一个连续公共字符串。

输入

一行,包含两个字符串,分别对应一个字符环。这两个字符串之间用单个空格分开。
字符串长度不超过255,且不包含空格等空白符。

输出

输出一个整数,表示这两个字符环上最长公共字符串的长度。

样例输入 

ABCEFAGADEGKABUVKLM MADJKLUVKL

样例输出

6

参考代码

#include <iostream>
#include <cstring>
using namespace std;

int findcommonlen(const string& str1,const string& str2){
	string s1,s2;
	s1=str1+str1;
	s2=str2+str2;
	int l1=s1.length(),l2=s2.length();
	int maxlen=0;
	for(int i=0;i<l1;i++){
		for(int j=0;j<l2;j++){
			int len=0;
			while(i+len<l1 && j+len<l2 && s1[i+len]==s2[j+len]){
				len++;
			}
			if(len==str1.length()) return str1.length();
			if(len==str2.length()) return str2.length();
			maxlen=max(maxlen,len);
		}
	}
	return maxlen;
}

int main(){
	string str1,str2;
	cin>>str1>>str2;
	cout<<findcommonlen(str1,str2)<<endl;
	return 0;
}

问题 B: 字符串最大跨距

题目描述

有三个字符串S1,S2,S,其中S长度不超过300,S1和S2的长度不超过10.想检测S1和S2是否同时在S中出现,且S1位于S2的左边,并在S中互不交叉(即S1的右边界点在S2的左边界点的左侧)。计算满足上述条件的最大跨距(即最大间隔距离:最右边的S2的起始点与最左边的S1的终止点之间的字符数目)。如果没有满足条件的S1,S2存在,则输出-1.
例如,S=abcd123ab888efghij45ef67kl,S1=ab,S2=ef,其中,S1在S中出现了2次,S2也在S中出现了2次,最大跨距为18.

输入

三个字符串,S,S1,S2,其间以逗号分隔。注意:S,S1,S2中均不含逗号和空格。

输出

S1和S2在S中的最大跨距;若S中没有满足条件的S1和S2,则输出-1.

样例输入

abcd123ab888efghij45ef67kl,ab,ef

样例输出

18

参考代码 

#include <iostream>
#include <cstring>
using namespace std;

int MaxSpan(const string& S,const string& S1,const string& S2){
	int maxSpan=-1;
	int s1Len=S1.length();
	int s2Len=S2.length();
	int sLen=S.length();
	for(int i=0;i<sLen;i++){
		bool matchS1=true;
		for(int j=0;j<s1Len;j++){
			if(S[i+j] != S1[j]){
				matchS1=false;
				break;
			}
		}
		if(matchS1){
			for(int k=i+s1Len;k<sLen;k++){
				bool matchS2=true;
				for(int l=0;l<s2Len;l++){
					if(S[k+l] != S2[l]){
						matchS2=false;
						break;
					}
				}
				if(matchS2){
					maxSpan=max(maxSpan,k-(i+s1Len));
				}
			}
		}
	}
	return maxSpan;
}

int main(){
	string S,S1,S2;
	getline(cin,S,',');
	getline(cin,S1,',');
	cin>>S2;
	cout<<MaxSpan(S,S1,S2)<<endl;
	return 0;
}

问题 C: 读入未知数目的string对象

题目描述

我们读入未知数目的string对象,每次输出对应的string对象编号和内容格式见样例

输入

任意多个字符串

输出

有多行一个编号由1开始后面对应内容,见样例

样例输入

Welcome to  
my world!

样例输出

1 Welcome
2 to​
3 my​
4 world!​

参考代码 

#include <iostream>
#include <cstring>
using namespace std;

int main(){
	string str;
	int n=1;
	while(cin>>str){
		cout<<n<<" "<<str<<endl;
		n++;
	}
	return 0;
}

问题 D: 连续出现的字符

题目描述

给定一个字符串,在字符串中找到第一个连续出现至少k次的字符。

输入

第一行包含一个正整数k,表示至少需要连续出现的次数。1 <= k <= 1000。
第二行包含需要查找的字符串。字符串长度在1到1000之间,且不包含任何空白符。

输出

若存在连续出现至少k次的字符,输出该字符;否则输出No。

样例输入

3
abcccaaab

样例输出

c

参考代码 

#include <iostream>
#include <cstring>
using namespace std;

int main(){
	int k;
	cin>>k;
	string str;
	cin>>str;
	char target=str[0];
	if(k==1) cout<<target<<endl;
	else{
		int count=1;
		for(int i=1;i<str.length();i++){
			if(str[i]==target){
				count++;
				if(count>=k){
					cout<<target<<endl;
					return 0;
				}
			}
			else{
				target=str[i];
				count=1;
			}
		}
		cout<<"No"<<endl;
	}
	return 0;
}

问题 E: 计算矩阵边缘元素之和

题目描述

输入一个整数矩阵,计算位于矩阵边缘的元素之和。所谓矩阵边缘的元素,就是第一行和最后一行的元素以及第一列和最后一列的元素。

输入

第一行分别为矩阵的列数n和行数m(m<100,n<100),两者之间以一个空格分开。

接下来输入的m行数据中,每行包含n个整数,整数之间以一个空格分开。

输出

输出对应矩阵的边缘元素和。

样例输入

3 3
3 4 1
3 7 1
2 0 1

样例输出 

15

参考代码 (这道题别学我,我肯定写复杂了)

#include <iostream>
using namespace std;

int main(){
	int n,m;
	cin>>n>>m;
	if(n==1){
		int res=0,a[m];
		for(int i=0;i<m;i++){
			cin>>a[i];
			res+=a[i];
		}
		cout<<res<<endl;
		return 0;
	}
	if(m==1){
		int res=0,b[n];
		for(int i=0;i<n;i++){
			cin>>b[i];
			res+=b[i];
		}
		cout<<res<<endl;
		return 0;
	}
	else{
		int matrix[100][100];
		for(int i=0;i<n;i++)
			for(int j=0;j<m;j++)
				cin>>matrix[i][j];
		int res=0;
		for(int i=0;i<n;i++){
			res+=matrix[0][i];
			res+=matrix[m-1][i];
		}
		for(int i=0;i<m;i++){
			res+=matrix[i][0];
			res+=matrix[i][n-1];
		}
		res-=(matrix[0][0]+matrix[0][m-1]+matrix[n-1][0]+matrix[n-1][n-1]);
		cout<<res<<endl;
	}
	return 0;
}

问题 F: 图像旋转

题目描述

输入一个n行m列的黑白图像,将它顺时针旋转90度后输出。

输入

第一行包含两个整数n和m,表示图像包含像素点的行数和列数。1≤n≤100,1≤m≤100。
接下来n行,每行m个整数,表示图像的每个像素点灰度。相邻两个整数之间用单个空格隔开,每个元素均在0~255之间。

输出

m行,每行n个整数,为顺时针旋转90度后的图像。相邻两个整数之间用单个空格隔开。

样例输入

3 3
1 2 3
4 5 6
7 8 9

样例输出

7 4 1
8 5 2
9 6 3

参考代码 

#include <iostream>
using namespace std;

int main(){
	int n,m;
	cin>>n>>m;
	int matrix[100][100];
	int rotated[100][100];
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++)
			cin>>matrix[i][j];
	}
	for(int i=0;i<m;i++){
		for(int j=0;j<n;j++)
			rotated[i][j]=matrix[n-1-j][i];
	}
	for(int i=0;i<m;i++){
		for(int j=0;j<n;j++){
			cout<<rotated[i][j]<<" ";
		}
		cout<<endl;
	}
	return 0;
}

问题 G: 【蓝桥杯2022初赛】统计子矩阵

题目描述

给定一个 N × M 的矩阵A,请你统计有多少个子矩阵(最小 1 × 1,最大 N × M) 满足:
子矩阵中所有数的和不超过给定的整数K?

输入

第一行包含三个整数N, M 和K.
之后 N 行每行包含 M 个整数,代表矩阵A.
30%的测试数据:1≤N,M≤20;
70%的测试数据:1≤N,M≤100;
100%的测试数据:1≤N,M≤500;0≤Aij≤1000;1≤K≤250000000。

输出

答案

样例输入

3 4 10
1 2 3 4
5 6 7 8
9 10 11 12

样例输出

19

提示

满足条件的子矩阵一共有19,包含:
大小为1 × 1 的有10 个。
大小为1 × 2 的有3 个。
大小为1 × 3 的有2 个。
大小为1 × 4 的有1 个。
大小为2 × 1 的有3 个。

参考代码(这道题不太会,题解参考以下链接)

[蓝桥杯 2022 省 B] 统计子矩阵


问题 H: 【蓝桥杯2022初赛】修建灌木

题目描述

爱丽丝要完成一项修剪灌木的工作。
有 N 棵灌木整齐的从左到右排成一排。
爱丽丝在每天傍晚会修剪一棵灌木,让灌木的高度变为 0 厘米。
爱丽丝修剪灌木的顺序是从最左侧的灌木开始,每天向右修剪一棵灌木。
当修剪了最右侧的灌木后,她会调转方向,下一天开始向左修剪灌木。
直到修剪了最左的灌木后再次调转方向。然后如此循环往复。
灌木每天从早上到傍晚会长高 1 厘米,而其余时间不会长高。
在第一天的早晨,所有灌木的高度都是 0 厘米。爱丽丝想知道每棵灌木最高长到多高。

输入

一个正整数N ,含义如题面所述。
30%的测试数据:1<N≤10;
100%的测试数据:1<N≤10000。

输出 

输出 N 行,每行一个整数,第 i 行表示从左到右第 i 棵树最高能长到多高。

样例输入

3

样例输出

4
2
4

 参考代码

#include <iostream>
using namespace std;

int main(){
	int n;
	cin>>n;
	if(n==1) cout<<1<<endl;
	else{
		for(int i=1;i<=n;i++)
			cout<<max((i-1)*2,(n-i)*2)<<endl;
	}
	return 0;
}

问题 I: 求和

题目描述

小T给你两个整数K和S,问你有多少个不同的三元组(X, Y, Z)满足:

  1. X+Y+Z=S
  2. 0≤X,Y,Z≤K

 输入

一行空格隔开的两个整数K和S,其中

  • 2≤K≤2500
  • 0≤S≤3K

 输出

满足条件的三元组的个数

样例输入

2 2

样例输出

6

 参考代码(这道题要注意时间限度)

#include <iostream>
using namespace std;

int main(){
	int k,s;
	cin>>k>>s;
	int count=0;
	for(int i=0;i<=k;i++){
		for(int j=0;j<=k;j++){
			if(k>=s-i-j && s-i-j>=0) count++;
		}
	}
	cout<<count<<endl;
	return 0;
}


问题 J: 等于没有比

题目描述

我们很悲哀地发现,像小L这样不补题的队员还有很多,这怎么回事呢?


教练们想要对队员们进行一次“抽查”,想找到有多少队员偷偷不补题。
虽然明面上是抽查,但是dddd,教练们必然要检查所有的队员。
但是每个教练的精力是有限的(下班了,饮茶先啦),每个教练最多最多只会去检查2*d+1个队员。
请问对于n位队员,最少要出动多少名教练? 

输入

队员的数量:1≤n≤20
教练的精力:1≤d≤20 

输出

所需最少的教练的数量

样例输入

6 2

样例输出

2

 参考代码

#include <iostream>
using namespace std;

int main(){
	int n,d;
	cin>>n>>d;
	if(n%(2*d+1)==0)
		cout<<n/(2*d+1)<<endl;
	else
		cout<<n/(2*d+1)+1<<endl;
	return 0;
}

问题 K: 补题抄题解

题目描述

在教练们的要求之下,所有的队伍都必须把之前的比赛全部补完。
但是摸鱼成瘾的队员们发现了bug,只要队伍里有一个人把题目补完,其他人就可以继续躺平了!那么问题来了,谁去当这个倒霉蛋呢……
 


因此,队里所有人都希望队伍里除去自己之外最卷的卷王当倒霉蛋。(有一说一,能者多劳是对无产阶级的压迫)
那么给出1~n号队员的内卷程度,请输出每位队员所希望的倒霉蛋的内卷程度。

输入

队员的数量2≤n≤200000
每位队员的内卷程度Ai:2≤Ai≤200000(1≤i≤n)

输出

第 i 位队员所希望的倒霉蛋的内卷程度

样例输入

3
1
4
3

样例输出

4
3
4

参考代码 

(注意:以下代码能实现题目要求但提交后时间超限

为使整个文章连贯些我还是把错误代码扔上来了

//以下代码不是AC代码!!
#include <iostream>
#include <algorithm>
using namespace std;

int main(){
	int n;
	cin>>n;
	int A[n],B[n];
	for(int i=0;i<n;i++){
		cin>>A[i];
		B[i]=A[i];
	}
	sort(B,B+n);
	int first=B[n-1],second=B[n-2];
	for(int i=0;i<n;i++){
		if(A[i]<first) cout<<first<<endl;
		else cout<<second<<endl;
	}
	return 0;
}
//以上代码不是AC代码!!

问题 L: 毛遂自荐2

题目描述

楚王想知道,没有前导零的从1 11到N NN的十进制数中,有多少个数的位数是奇数。

  • 1 11有1 11位
  • 9 99有1 11位
  • 10 1010有2 22位
  • 123 123123有3 33位

此时有名毛遂者,自荐以解此题。

输入

输入包括1 11行1 11个整数N NN

数据范围:

  • 1 ≤ N ≤ 1 0 5 1leq Nleq 10^51≤N≤105

输出

输出1 11行1 11个整数,代表1 11到N NN中,有多少个数的位数是奇数

例如从1 11到136 136136这136 136136个数,1 , 2 , ⋯ 9 1,2,cdots91,2,⋯9有1 11位(9个),100 , 101 , ⋯   , 136 100,101,cdots,136100,101,⋯,136有3 33位(37个),因此共有46 4646个数的位数是奇数。

样例输入

136

样例输出

46

参考代码 

#include <iostream>
using namespace std;

int main(){
	int n;
	cin>>n;
	int count=0;
	for(int i=1;i<=n;i++){
		int num=i,digit=0;
		while(num){
			num/=10;
			digit++;
		}
		if(digit%2==1) count++;
	}
	cout<<count<<endl;
	return 0;
}

问题 M: Bob和Alice(4)

题目描述

输入

n
1 <= n <= 10^9

输出 

 

样例输入

2

样例输出

1

 提示

参考代码 (这道题主要就是要找到规律)

#include <iostream>
using namespace std;

int main(){
	long long n;
	cin>>n;
	cout<<n*(n-1)/2<<endl;
	return 0;
}

原谅我数学不好,剩下的题不会了,把题先放上来

相信聪明的你一定可以解决


问题 N: Bob和Alice(5)

题目描述

输入 

输出

样例输入

3
2 3 1

样例输出

5

 提示

 

 参考代码

略(不会)

问题 O: Bob和Alice(6)

题目描述 

输入

输出 

是否该序列的多重集可以等于该病毒游戏在经过n秒之后的多重集 
如果是打印 Yes
否则打印 No

样例输入

2
4 2 3 1

样例输出

Yes

提示

一开始,我们生成一个属性值为4的病毒
第1s之后,属性值为4的病毒繁殖生成了一个属性值为3的病毒
第2s之后,属性值为4的病毒繁殖生成了一个属性值为2的病毒
属性值为3的病毒繁殖生成了一个属性值为1的病毒
所以该序列的多重集 {1,2,3,4} = n秒之后的多重集 {1,2,3,4} 
是符合题意的

参考代码

略(不会)

问题 P: Monster Hunter

题目描述

不知道大家有没有玩过这款游戏哈
在这游戏中经常是一条龙好几万滴血,玩家砍一刀50
(这不是楞折磨人吗)
话说xsb同学是一位猎龙高手
(但砍一条龙也要好长时间)

 输入

 

输出

输出一个整数,代表满足条件神器的数量

样例输入

6

样例输出

3

提示

对于N等于6,我们有三个神器可以选择,分别是2 5 6
对于2   6->3->1
对于5   6->1
对于6   6->1

参考代码

略(不会)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值