2020年第十届C/C++ B组第二场蓝桥杯省赛真题

第一次参加蓝桥杯,做几套真题适应一下。

第一题:门牌制作

题目描述
小蓝要为一条街的住户制作门牌号。这条街一共有2020位住户,门牌号从1到2020编号。小蓝制作门牌的方法是先制作0到9这几个数字字符,最后根据需要将字符粘贴到门牌上,例如门牌1017需要依次粘贴字符1、0、1、7,即需要1个字符0,2个字符1,1个字符7。请问要制作所有的1到2020号门牌,总共需要多少个字符2?

题目分析

前面几题直接爆搜,拼的就是速度

题目代码

ll judge(int a) {
	ll sum = 0;
	while (a) {
		if (a % 10 == 2) sum++;

		a /= 10;
	}
	return sum;
}


int main()
{
	ll sum = 0;
	for (int i = 1; i <= 2020; i++) {
		sum += judge(i);
	}
	cout << sum << endl;


	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
	return 0;
}  

答案:624

第二题:既约分数

题目描述
如果一个分数的分子和分母的最大公约数是1,这个分数称为既约分数。例如,3/4,5/2,1/8,7/1都是既约分数。请问,有多少个既约分数,分子和分母都是1到2020之间的整数(包括1和2020)

题目分析
爆搜

题目代码

int main()
{
	ll sum = 0;
	for (int i = 1; i <= 2020; i++) {
		for (int j = 1; j <= 2020; j++) {
			if (gcd(i, j) == 1) sum++;
		}
		
	}
	cout << sum << endl;


	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
	return 0;
}  

答案:2481215

第三题:蛇形填数

题目描述
如下图所示,小明用从1开始的正整数“蛇形”填充无限大的矩阵。容易看出矩阵第二行第二列中的数是5。请你计算矩阵中第20行第20列的数是多少?

1 2 6 7 15 …
3 5 8 14 …
4 9 13 …
10 12 …
11 …

题目分析

模拟就完了

代码:

int main()
{
	int dp[50][60] = {0};
	dp[1][1] = 1;

	int a = 1, b = 1;
	int judge=0;
	int summ = 1000;
	while (dp[20][20]==0) {
		cout << a << " " << b <<" "<

答案:761

第四题:跑步锻炼

题目描述
小蓝每天都锻炼身体。正常情况下,小蓝每天跑1千米。如果某天是周一或者月初(1日),为了激励自己,小蓝要跑2千米。如果同时是周一或月初,小蓝也是跑2千米。小蓝跑步已经坚持了很长时间,从2000年1月1日周六(含)到2020年10月1日周四(含)。请问这段时间小蓝总共跑步多少千米?

题目分析
20354 ~= 110^4 还说啥直接暴力枚举周一,和月初就完了
虽然我的写法丑了点,但是这样不用动脑啊,hhh~~

题目代码


int year[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31 };

int main()
{
	ll sum = 0;
	int monday = 6;
	for (int i = 2000; i <= 2019; i++) {
		if (i % 4 == 0 || (i % 400 == 0 && i % 100 != 0)) {
			year[2] = 29;
		}
		else year[2] = 28;

		for (int j = 1; j <= 12; j++){
			for (int k = 1; k <= year[j]; k++) {
				if (k == 1 || monday == 1) sum += 2;
				else sum++;


				monday++;
				if (monday == 8) monday = 1;
			}
		}
	}

	int i = 2020;

		if (i % 4 == 0 || (i % 400 == 0 && i % 100 != 0)) {
			year[2] = 29;
		}
		else year[2] = 28;

		for (int j = 1; j <= 9; j++){
			for (int k = 1; k <= year[j]; k++) {
				if (k == 1 || monday == 1) sum += 2;
				else sum++;


				monday++;
				if (monday == 8) monday = 1;
			}
		}



		sum += 2;    //10月初一





	cout << sum << endl;


	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
	return 0;
}  

题目答案:8879

第五题:七段码

题目描述
小蓝要用七段码数码管来表示一种特殊的文字。
七段码上图给出了七段码数码管的一个图示,数码管中一共有 7 段可以发光的二极管,分别标记为 a, b, c, d, e, f, g。小蓝要选择一部分二极管(至少要有一个)发光来表达字符。在设计字符的表达时,要求所有发光的二极管是连成一片的。
例如:b 发光,其他二极管不发光可以用来表达一种字符。
例如:c 发光,其他二极管不发光可以用来表达一种字符。这种方案与上一行的方案可以用来表示不同的字符,尽管看上去比较相似。
例如:a, b, c, d, e 发光,f, g 不发光可以用来表达一种字符。
例如:b, f 发光,其他二极管不发光则不能用来表达一种字符,因为发光的二极管没有连成一片。
请问,小蓝可以用七段码数码管表达多少种不同的字符?

题目分析
既然亮的灯一定要联通,那么可以将7个点都将其作为起点开始dfs,只要满足联通且不亮,那么就继续dfs,具体思路已写在代码中
题目代码

int ve[8][8];   //用来表示x-y是否联通

void uoin(int a, int b) {
	ve[a][b] = 1;
	ve[b][a] = 1;
}

int visit[8];

set >se;     //记录灯亮的情况   这里我觉得完全可以用string来代替visit和set,但是还是借鉴一下大佬的写法比较好理解

void dfs(int a, sets) {
	if (se.find(s) == se.end()) {    //没找到,所以需要记录这一种情况
		se.insert(s);
	}


	for (int i = 1; i <= 7; i++) {
		if (visit[i] == 1 || ve[a][i] == 0) continue;   //灯已经亮了或者不相连

		cout << a << " " << i << endl;
		s.insert(i);
		visit[i] = 1;
		dfs(i,s);
		visit[i] = 0;
		s.erase(i);

	}
}

int main()
{
	uoin(1, 2);
	uoin(1, 6);


	uoin(2, 3);
	uoin(2, 7);

	uoin(3, 7);
	uoin(3, 4);

	uoin(4, 5);


	uoin(5, 6);
	uoin(5, 7);

	uoin(6, 7);
	
	memset(visit,0,sizeof(visit));

	sets;

	for (int i = 1; i <= 7; i++) {
		s.insert(i);
		visit[i] = 1;
		dfs(i, s);         //以i灯亮为起点开始dfs
		visit[i] = 0;
		s.erase(i);

		cout << endl << endl;
	}


	cout << se.size() << endl;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
	return 0;
}  

第六题:成绩统计

题目描述
小蓝给学生们组织了一场考试,卷面总分为100分,每个学生的得分都是一个0到100的整数。如果得分至少是60分,则称为及格。如果得分至少为85分,则称为优秀。请计算及格率和优秀率,用百分数表示,百分号前的部分四舍五入保留整数。
【输入格式】 输入的第一行包含一个整数n,表示考试人数。接下来n行,每行包含一个0至100的整数,表示一个学生的得分。
【输出格式】 输出两行,每行一个百分数,分别表示及格率和优秀率。百分号前的部分四舍五入保留整数。
【样例输入】
7
80
92
56
74
88
100
0
【样例输出】
71%
43%

题目分析
水题

题目代码

int main()
{
	int n;
	while (cin >> n) {
		int a;
		double sum1 = 0;
		double sum2 = 0;
		for (int i = 0; i < n; i++) {
			cin >> a;
			if (a >= 60) sum1++;
			if (a >= 85) sum2++;
		}
		sum1 = sum1 * 100 / n;
		sum2 = sum2 * 100 / n;
		printf("%d\n%d\n", int(sum1 + 0.5), int(sum2 + 0.5));
	}
	return 0;
}  

第七题:回文日期

题目描述
2020年春节期间,有一个特殊的日期引起了大家的注意:2020年2月2日。因为如果将这个日期按“yyyymmdd”的格式写成一个8位数是20200202,恰好是一个回文数。我们称这样的日期是回文日期。有人表示20200202是“千年一遇”的特殊日子。对此小明很不认同,因为不到2年之后就是下一个回文日期:20211202即2021年12月2日。也有人表示20200202并不仅仅是一个回文日期,还是一个ABABBABA型的回文日期。对此小明也不认同,因为大约100年后就能遇到下一个ABABBABA型的回文日期:21211212即2121年12月12日。算不上“千年一遇”,顶多算“千年两遇”。给定一个8位数的日期,请你计算该日期之后下一个回文日期和下一个ABABBABA型的回文日期各是哪一天。
【输入格式】
输入包含一个八位整数N,表示日期。
【输出格式】
输出两行,每行1个八位数。第一行表示下一个回文日期,第二行表示下一个ABABBABA型的回文日期。
【样例输入】
20200202
【样例输出】
20211202
21211212
【评测用例规模与约定】
对于所有评测用例,10000101 <= N <= 89991231,保证N是一个合法日期的8位数表示。
题目分析:
预处理打表大法好!!!!
(但是看了一下别人的代码发现好像直接暴力就行了??????)

题目代码

int year[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };

string judge(int i, int j, int k) {
	string s = "";
	s = to_string(i);
	if (j <= 9) {
		string temp = "0" + to_string(j);
		s += temp;
	}
	else s += to_string(j);

	if (k <= 9)
	{
		string temp = "0" + to_string(k);
		s += temp;
	}
	else s += to_string(k);


	return s;
}

bool huiwen(string s) {
	int i = 0;
	int j = s.size()-1;
	while (i <= j) {
		if (s[i] != s[j]) {
			return false;
		}
		i++;
		j--;
	}
	return true;
}


bool ABAB(string s) {

	if (s[0] == s[2] && s[2] == s[5] && s[5] == s[7] && s[1] == s[3] && s[3] == s[4] && s[4] == s[6]) return true;
	return false;
}


int main()
{
	/*
	vectorvex;
	int sum = 0;

	for (int i = 10000; i <= 11000; i++) {    //要注意的是还要防止出89991231这样的数据

		if (i % 4 == 0 && i % 400 == 0 || i % 100 != 0) year[2] = 29;
		else year[2] = 28;
		for (int j = 1; j <= 12; j++) {

			for (int k = 1; k <= year[j]; k++) {
				string s = judge(i, j, k);

				if (ABAB(s)) {
					sum++;
					vex.push_back(s);
				}
			}
		}
	}




	for (int i = 0; i < vex.size(); i++) {
		if (i == 0) cout << vex[i];
		else cout << "," << vex[i];
	}
	*/
	/*
	vectorve;
	int sum = 0;
	for (int i = 1000; i <= 9000; i++) {    //要注意的是还要防止出89991231这样的数据
		
		if (i % 4 == 0 && i % 400 == 0 || i % 100 != 0) year[2] = 29;
		else year[2] = 28;
		for (int j = 1; j <= 12; j++) {
			
			for (int k = 1; k <= year[j]; k++) {
				string s = judge(i, j, k);

				if (huiwen(s)) {
					sum++;
					ve.push_back(s);
				}
			}
		}
	}

	cout << sum << endl;


	int sum = 0;
	for (int i = 9000; i <= 100000; i++) {    //要注意的是还要防止出89991231这样的数据
		if (sum == 2) break;
		if (i % 4 == 0 && i % 400 == 0 || i % 100 != 0) year[2] = 29;
		else year[2] = 28;
		for (int j = 1; j <= 12; j++) {
			if (sum == 2) break;
			for (int k = 1; k <= year[j]; k++) {
				if (sum == 2) break;
				string s = judge(i, j, k);

				if (huiwen(s)) {
					sum++;
					ve.push_back(s);
				}
			}
		}
	}

	cout << ve[0] << " " << ve[1] << endl;
	*/
	

	vectorve={10011001,10100101,10111101,10200201,10211201,10300301,10400401,10500501,10600601,10700701,10800801,10900901,11011011,11100111,11111111,11200211,11211211,11300311,11400411,11500511,11600611,11700711,11800811,11900911,12011021,12100121,12111121,12200221,12211221,12300321,12400421,12500521,12600621,12700721,12800821,12900921,13011031,13100131,13211231,13300331,13500531,13700731,13800831,20011002,20100102,20111102,20200202,20211202,20300302,20400402,20500502,20600602,20700702,20800802,20900902,21011012,21100112,21111112,21200212,21211212,21300312,21400412,21500512,21600612,21700712,21800812,21900912,22011022,22100122,22111122,22200222,22211222,22300322,22400422,22500522,22600622,22700722,22800822,22900922,30011003,30100103,30111103,30200203,30211203,30300303,30400403,30500503,30600603,30700703,30800803,30900903,31011013,31100113,31111113,31200213,31211213,31300313,31400413,31500513,31600613,31700713,31800813,31900913,32011023,32100123,32111123,32200223,32211223,32300323,32400423,32500523,32600623,32700723,32800823,32900923,40011004,40100104,40111104,40200204,40211204,40300304,40400404,40500504,40600604,40700704,40800804,40900904,41011014,41100114,41111114,41200214,41211214,41300314,41400414,41500514,41600614,41700714,41800814,41900914,42011024,42100124,42111124,42200224,42211224,42300324,42400424,42500524,42600624,42700724,42800824,42900924,50011005,50100105,50111105,50200205,50211205,50300305,50400405,50500505,50600605,50700705,50800805,50900905,51011015,51100115,51111115,51200215,51211215,51300315,51400415,51500515,51600615,51700715,51800815,51900915,52011025,52100125,52111125,52200225,52211225,52300325,52400425,52500525,52600625,52700725,52800825,52900925,60011006,60100106,60111106,60200206,60211206,60300306,60400406,60500506,60600606,60700706,60800806,60900906,61011016,61100116,61111116,61200216,61211216,61300316,61400416,61500516,61600616,61700716,61800816,61900916,62011026,62100126,62111126,62200226,62211226,62300326,62400426,62500526,62600626,62700726,62800826,62900926,70011007,70100107,70111107,70200207,70211207,70300307,70400407,70500507,70600607,70700707,70800807,70900907,71011017,71100117,71111117,71200217,71211217,71300317,71400417,71500517,71600617,71700717,71800817,71900917,72011027,72100127,72111127,72200227,72211227,72300327,72400427,72500527,72600627,72700727,72800827,72900927,80011008,80100108,80111108,80200208,80211208,80300308,80400408,80500508,80600608,80700708,80800808,80900908,81011018,81100118,81111118,81200218,81211218,81300318,81400418,81500518,81600618,81700718,81800818,81900918,82011028,82100128,82111128,82200228,82211228,82300328,82400428,82500528,82600628,82700728,82800828,82900928 ,90011009 ,90100109 };
	vectorve1 = { 10100101,11111111,20200202,21211212,30300303,40400404,50500505,60600606,70700707,80800808,90900909};

	ll s;

	while (cin >> s) {

		int a = upper_bound(ve.begin(), ve.end(), s) - ve.begin();

		int b = upper_bound(ve1.begin(), ve1.end(), s) - ve1.begin();


		cout << ve[a] << endl << ve1[b] << endl;
	}
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
	return 0;
}  

第八题:子串分值和

题目描述
对于一个字符串 S,我们定义 S 的分值 f (S ) 为 S 中出现的不同的字符个
数。例如 f (”aba”) = 2, f (”abc”) = 3, f (”aaa”) = 1。
现在给定一个字符串 S [0::n − 1](长度为 n),请你计算对于所有 S 的非空
子串 S [i:: j](0 ≤ i ≤ j < n), f (S [i:: j]) 的和是多少。
【输入格式】
输入一行包含一个由小写字母组成的字符串S。
【输出格式】
输出一个整数表示答案。
【样例输入】
ababc
【样例输出】
28
【样例说明】
子串 f值
a 1
ab 2
aba 2
abab 2
ababc 3
b 1
ba 2
bab 2
babc 3
a 1
ab 2
abc 3
b 1
bc 2
c 1

题目分析
题目代码

第九题:平面切分

题目描述
平面上有N 条直线,其中第i条直线是y = Ai x+Bi
请计算这些直线将平面分成了几个部分。
【输入格式】
输入的第一行包含一个整数N, 以下N行,包含两个证书 Ai,Bi
【输出格式】 一个整数代表答案
【样例输入】
31
1
2 2
3 3
【样例输出】
6

题目分析
定理:对于新增一条线,增加的空间个数==新增线后所有的交点+1
题目代码

struct point {
	int a, b;
}p[100000];

int main()
{
	int n;
	while (cin >> n) {
		set>se;   //线去重  //y=ax+b   a和b都不一样即为新的线
		for (int i = 0; i < n; i++) {
			int a, b;
			cin >> a >> b;
			se.insert(make_pair(a, b));
		}
		int cnt = 0;
		for (auto it = se.begin(); it != se.end(); it++) {
			p[cnt].a = it->first;
			p[cnt++].b = it->second;  //因为set不支持下标寻址,所以必须用个数组存一下
		}
		ll sum = 2;    //一定有一根线把平面分为2个


		set>s;   //存交点

		for (int i = 1; i < cnt; i++) {

			for (int j = 0; j < i; j++) {
				int a = (p[j].b - p[i].b) / (p[i].a - p[j].a);                      //两条不同的线必有交点
				int b = (p[i].b*p[j].a - p[j].b*p[i].a)/(p[j].a - p[i].a);
				s.insert(make_pair(a, b));
			}
			sum += s.size() + 1;
		}

		cout << sum << endl;
	}	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
	return 0;
}  

第十题:字串排序

题目描述
小蓝最近学习了一些排序算法,其中冒泡排序让他印象深刻。
在冒泡排序中,每次只能交换相邻的两个元素。小蓝发现,如果对一个字符串中的字符排序,只允许交换相邻的两个字符,则在所有可能的排序方案中,冒泡排序的总交换次数是最少的。
例如,对于字符串 lan 排序,只需要 1 次交换。对于字符串 qiao 排序,总共需要 4 次交换。
小蓝找到了很多字符串试图排序,他恰巧碰到一个字符串,需要 V 次交换,可是他忘了把这个字符串记下来,现在找不到了。
请帮助小蓝找一个只包含小写英文字母且没有字母重复出现的字符串,对该串的字符排序,正好需要 V 次交换。如果可能找到多个,请告诉小蓝最短的那个。如果最短的仍然有多个,请告诉小蓝字典序最小的那个。请注意字符串中可以包含相同的字符。
【输入格式】
输入的第一行包含一个整数V,小蓝的幸运数字。
【输出格式】
题面要求的一行字符串。
【样例输入】
4
【样例输出】
bbaa
【样例输入】
100
【样例输出】
jihgfeeddccbbaa

题目分析

题目代码

你可能感兴趣的:(C++)