2018年第九届蓝桥杯大赛软件类省赛C/C++B组参赛感想

时间:2022-09-10 14:51:44

    本人大二,学校非985,非211,非双一流,普通一本编程小白一枚,今年第一次入蓝桥杯的坑,比赛之后颇有感触,今日写下某些我会做的题解,还不知答案和个人成绩,所以也不敢妄言,大佬勿喷。

     第一道签到题,2000年1月1日是第一天,5月4日是第几天。这道题没有写代码,直接草稿纸手算,需要注意二月有29天。31+29+31+30+4=125,不知对不对。有大佬直接用Excel做出来了,看来我还是技不如人啊。
     第二道题貌似有点难度了,反正我一眼没看懂,后来明白了,题意大概是:汉字字形可以用16*16的像素表示,每个像素有两种状态,对应二进制数0和1,于是一个汉字就可以用256位二进制数表示,也就是32个字节。题目给出的是十组数据表示十个汉字的字形,每组数据为32个带符号十进制数( 对应八位二进制数,符号位为第一位),题目嘛,就是这十个字组成的一句话。首先写个程序把汉字显示出来:先把十进制数转化为二进制,用个二维数组存储,然后按条件打印出来好了。代码如下:
#include <iostream>
#include <cstdio>
#include <cmath>

using namespace std;

int s[32][8]={0};

int main() {
	for(int i=0;i<32;i++) {
		int num;
		scanf("%d",&num);
		if(num<0) {
			s[i][0]=1;
			num=-num;
		}
		int temp=num;
		for(int j=7;j>0;j--) {
			s[i][j]=temp%2;
			temp/=2;
		}
	}
	for(int i=0;i<16;i++) {
		for(int j=0;j<8;j++)
			printf(s[2*i][j]==1?"*":" ");
		for(int j=0;j<8;j++)
			printf(s[2*i+1][j]==1?"*":" ");
		printf("\n");
	}
	return 0;
}
通过程序运行得到题目:"九的九次方等于多少?"然后在电脑上随便找个计算器,得到答案:387420489.


        第三道题好像是题目给出100个数,求它们的乘积末尾有几个零。看一下这些数的范围,都是三位或四位数,所以算乘积肯定算不出来。不知是不是个套路(至少我以前没有想到或是看到过,可能我读书太少吧),仔细一想,乘积末尾是0不就是能被十整除吗,而10都是通过2*5得到的,所以只需要知道这100个数中因子2和5的个数,其中较小的那个数应该就是答案了。代码如下:
#include <iostream>
#include <cstdio>

using namespace std;

int main() {
	int five=0,two=0;
	for(int i=0;i<100;i++) {
		int num;
		scanf("%d",&num);
		while(num%5==0) {
			five++;
			num/=5;
		}
		while(num%2==0) {
			two++;
			num/=2;
		}
	}
	printf("two=%d\nfive=%d\n",two,five);
	return 0;
}

数据记不清了,所以具体答案就不说了。


        第四题是个x星球人摔手机的问题,本人很菜,硬是没读懂这道题到底是什意思,答案也是随手填的,有大佬会这道题的可以带我一下。

        第五题代码填空,好像是求一个集合里第k小的数是几,填空部分是快速排序的递归部分的四个参数,代码记不清了,反正也不是很难,答案就先跳过吧。

        第六题题意很简单:大概是说从A,B,C三个数组中各选一个数字a,b,c,使a<b<c,这样的选法有几种。我的想法也很简单:先分别对A数组,B数组,C数组进行排序,排好后对B组中的元素逐一遍历,到A中找小于B中的这个元素的数的个数,到C中 找大于B中的这个元素的数的个数,得到的两个结果相乘,最后对乘积结果求和就得到答案啦。代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn=100000;
int A[maxn],B[maxn],C[maxn];

int main() {
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++) {
		scanf("%d",&A[i]);
	}
	sort(A,A+n);
	for(int i=0;i<n;i++) {
		scanf("%d",&B[i]);
	}
	sort(B,B+n);
	for(int i=0;i<n;i++) {
		scanf("%d",&C[i]);
	}
	sort(C,C+n);
	int sum=0;
	for(int i=0;i<n;i++) {
		int j;
		for(j=0;j<n;j++) {
			if(A[j]>=B[i])
				break;
		}
		int sum1=j;
		for(j=n-1;j>=0;j--) {
			if(C[j]<=B[i])
				break;
		}
		int sum2=n-j-1;
		sum+=(sum1*sum2);
	}
	printf("%d",sum);
	return 0;
}

        第七题求平面上从原点开始经过弯弯曲曲的折线到达一个整点的距离。看了一眼,感觉是一道搜索题,然后看数据范围貌似有点大,又看第二眼我就考虑着这题会不会是简单的数学公式。经过一番分析后,我发现好像真能用数学公式分情况计算出答案,只是不是太简单。先比较一下输入的横、纵坐标的绝对值,分|x|>|y|和|x|<=|y|两种情况。然后按x的正负,y的正负进行讨论得求值公式。根据图形中的横线和竖线可以看出公式应该是[(1+2+3+……+m)+ (1+2+3+……+n)+k](其中m,n和点所在的边是上下左右有关,k是最后一条边拐角处到要求点的距离,前两项是等差数列的和)。代码如下:

#include <iostream>
#include <cstdio>
#include <cmath>

using namespace std;

long long dis(int x,int y) {
	int m=abs(x);
	int n=abs(y);
	if(m>n) {
		if(x<0) {
			long long num=(long long)(2*m-1);
			long long dx=(num+1)*num/2;
			long long dy=(num-1)*num/2;
			long long d=(long long)(y-x-1);
			return (dx+dy+d);
		}
		else {
			long long num=(long long)(2*m);
			long long dx=(num+1)*num/2;
			long long dy=(num-1)*num/2;
			long long d=(long long)(x-y);
			return (dx+dy+d);
		}
	}
	else {
		if(y<=0) {
			long long num=(long long)(2*n);
			long long dx=(num+1)*num/2;
			long long dy=(num+1)*num/2;
			long long d=(long long)(-y-x);
			return (dx+dy+d);
		}
		else {
			long long num=(long long)(2*m-1);
			long long dx=(num+1)*num/2;
			long long dy=(num+1)*num/2;
			long long d=(long long)(x+y);
			return (dx+dy+d);
		}
	}
}

int main() {
	int x,y;
	scanf("%d%d",&x,&y);
	printf("%lld",dis(x,y));
	return 0;
}

写的乱七八糟,不知道对与不对。

        前面的题浪费的时间太多了(也可能是智商跟不上),后面三道题就没有时间了,离考试结束 还有二十分钟的时候瞥了一眼后面的三道题,第九个好像是个搜索的题目(日常恶心),不过好像不是太难,然后开始写,最后还是没写完。。。

        个人感觉这次比赛并没有几个算法题目(至少前七题是这样),但是今后还是要好好学算法呐,不然智商就真的蹭蹭地下降了。。。真希望这次比赛能拿个奖,然后,没有然后了,来年再战,吼吼。