关于广西大学20级第一次段考的题解和牢骚

##关于广西大学20级第一次段考的题解和牢骚

前文牢骚

首先要明确,题目不难,甚至可以说是简单,六题除了卡格式和卡时长没有很大的问题。最大的问题是之前的题目出的太简单或者太难,导致中等题做的太少,程序优化次数太少,超时和卡格式现象频出。数据太弱,伪代码都能轻易过关。
其次,在比赛前晚上模题我也感觉难度上略高,但在卡了我们数据的前提下也伪ak了(指有一题数据有问题就没模过)。 
最后吧,希望大家认真学习好代码,有自己的一技之长,最好能有一个自己感兴趣的项目(比如算法,比如前端,比如后端,比如数据处理,比如视图,比如游戏),这一切都基于,你的代码是好的,而不只是对的。

正文部分,题解

题一:打印菱形

题意:给你一个方程,让你去模拟一个图像。如果这题放在比赛,五分钟第一个ac不是问题。
现在来讲一下比较有效的思路,第一是在草稿纸上建立坐标系,把这些点画在坐标系里面,思考这个方程函数如何和坐标系联系在一起,如果可以,你会用怎样的办法去建立这个函数。
第二种可能可行的思路,暴力打印,用if语句判定这个点是否落在了一个区间,如果是,那就打印。这个区间就是总长/2-该行的点数,总长/2+该行打印的点数。
很多同学群里提问吧,我个人理解是之前做的题目没有遇到过太多根据题意模拟的题,单纯是打印了一个自己想当然的菱形(这个lcx可能全责),但是永远要明白,只有根据题意模拟的题才是有灵魂的,纯看样例的模拟会出大问题。
代码中没有注释会难以消化所以建议自己先写。

long long sum = 2 + b * (a - 1);//long long 长整型(防爆破)
	for (long long  i = 1;i <= a;i++) {
    
    
			for (long long j = 1;j <= sum;j++) {
    
    
				if (j <= sum / 2 - b * (i - 1) / 2 - 1) printf(" ");
				else if (j > sum / 2 - b * (i - 1) / 2 - 1 && j <= sum / 2 + b * (i - 1) / 2 + 1) printf("*");
			}
			printf("\n");
		}
		for (long long i = a;i >= 1;i--) {
    
    
			for (long long j = 1;j <= sum;j++) {
    
    
				if (j <= sum / 2 - b * (i - 1) / 2 - 1) printf(" ");
				else if (j > sum / 2 - b * (i - 1) / 2 - 1 && j <= sum / 2 + b * (i - 1) / 2 + 1) printf("*");
			}
			printf("\n");//每次都是这种问题
			
		}`

题二:签到题

题意,给你一个数字,判定他是否被9996整除,如果是,打印,如果不是,继续判定,是否被49整除,如果是,打印,如果不是,输出不是的打印。
这题难可能在输出格式上??我估计很多人之前没有接触过这样的打印规则,所以全死了。也可能以前做题太少,或者随手抄抄别人代码就过了,就没管过输出格式。

if (n % 9996 == 0)printf("SurplusYYDS\n");
		else if (n % 49 == 0)printf("????\n");
		else printf("AWSL\n");

代码也无所谓的,这题确实有手就行。

题三:小小数论题

给你一个函数,找出1-99整数中最接近零的函数值。
巧妙运用double ,fabs,pow基本都能过,关键在于你这些函数会不会背。
同样也是有人问我这个很有意思的问题,用选择排序把一百种情况理论上排序出来(细想可能不会爆,但是非常费时间)
我个人理解的最好思路是直接用两个变量ans和p,前者存最小的数据,后者存最小数据的下标。通过比大小来判定这个数据是否是最小数据,并将这个最小数据的下标存入p中
(仔细想来我的思路已经有点动态规划的意思了)

for (int i = 1;i < 100;i++) {
    
    
			if (ans > fabs(n * pow(i, 3) + m * i - x)) {
    
    
				ans = fabs(n * pow(i, 3) + m * i - x);
				p = i;
			}
		}

题四:辗转相减法

辗转相除的弟弟,不过和小模拟结合原以为会卡掉一片,没想到大多数人都还是明白了题意去模拟,说明模拟不难,难的是思路。这就和第一题形成了鲜明的对比了。
这题我讲一下我理解的优化点,可以用while(n!=m)判定,这样只需要考虑m>n和m<n两种请况。也就能用六行代码解决问题。

while (n != m) {
    
    
			if (n > m) {
    
    
				printf("%lld-%lld=%lld\n", n, m, n - m);
				n -= m;
			}
			if (n < m) {
    
    
				printf("%lld-%lld=%lld\n", m, n, m - n);
				m -= n;
			}
		}

题五:第二大数字

这题cm感觉背锅,数据造的有点大

首先题面没有想卡你们的意思,这题确实再高两个数量级也能过。但是如果是我做这题,我肯定不会想到排序,而是用搜索。排序是什么,是把一堆无序的东西变有序,搜索是查找你需要的东西。那么这题就很简单了。什么是你要的呢,你要第二大的数字,那么你怎么知道他是第二大呢?
我们可以理解一下,当我们知道了最大的那个数字,是不是理所当然把那个最大值剔除了就是第二大了呢?那么下次问你找第三大,第四大,是不是原理就很显然了呢?
但其实我们还可以更加高效的去思考,我们一遍一遍找最大值,第二大值,第三大值,为什么不一次就找齐呢?
其实这是我觉得最有意思的一题,因为集训队刚开始很多c++选手的思路都是sort一下就完事了,但我觉得这题的复杂度没必要用sort,反而是on。
听完我吹逼就讲正事,我们可以在输入每一个数的时候比较大小,然后把最大的数字存到max里,但是这时候max原本的数字就变成了第二大的数字,就给了max2;如果有一个数他比max小但是比max2大,那就很显然了啊,他就是我们想的第二大的值。

while (n--) {
    
    
			scanf("%lld", &m);
			if (p < m) {
    
    
				ans = p;
				p = m;

			}
			else if (ans < m) {
    
    
				ans = m;
			}
		}
		printf("%lld\n", ans);

题六:字符串输出

有朋友问我,这些题目是不是都要用数组存才能做?我和他这么说,理论上,没有一题必须用数组,但我个人习惯上最后一题还是用了数组做。
先讲一下不用数组的思路,查找c 是否出现,没出现则打印出来,出现了就存进一个新变量里来防止自己忘记。接下来再输入一个数,看看这个数是不是m,如果不是,那就回头把c打印出来,如果是,那就两个都可以清空了,直接自觉地的打印lyf。以此类推。
再讲用数组的思路,先存再查,查了之后不打印,直到出现了cm再打印,并且把lyf打印进去。不过这个思路缺点是最后还要把多余的数组都打印出来,就会麻烦一点。我不讲究,不是字符串选手,有个思路就可,不至于手足无措。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<math.h>
char a[200005];
int main() {
    
    
	int t;
	scanf("%d", &t);
	while (t--) {
    
    
	    long long  n,m;
		long long  ans;
		long long  p;	
		p = 1;
		int flag = 0;
		scanf("%lld\n", &n);
		for (long long  i = 1;i <= n;i++) {
    
    
			scanf("%c\n", &a[i]);
			
			 if (a[i-1]=='c' && a[i] == 'm') {
    
    
				for (long long  j = p;j <= i - 2;j++) {
    
    
					printf("%c", a[j]);

				 }
				printf("lyf");
				p = i + 1;
			}
	    }
		for (long long  i = p;i <= n;i++) {
    
    
			printf("%c", a[i]);
		}
		printf("\n");

	}
	return 0;
}

给看到最后一题的同学一些奖励,最后一题直接上完整代码,虽然这是写的最垃圾的一题哈哈。很多前面的变量都延用方便快速k题。

总结

给看到这里的小朋友一点奖励,讲一些我半小时a题的心得,也算是集训队第二次比赛总结出来的经验。
打代码首先要自己看得懂,要用一些自己最常用的名字命名,要看个人习惯,有的人打字快而且丢三落四,建议多打几个字母告诉自己这个叫什么。像我这种记不住人名的人就喜欢用abcd(友人A),而且基本上都是同一套东西,n就是循环次数,t就是几个样本。变量abc,数组xy巴拉巴拉。
 然后就是头文件的打印,每一题的头文件都是重复的,还不如直接复制粘贴一下,自己存一个板子在电脑里,然后做题的时候复制粘贴一下
其他比如说板子,很多人问我板子是什么,板子其实就是你做题一些封装的函数,比如说gcd(辗转相除法),比如说sort(快速排序),还有像冒泡排序,选择排序,甚至质数筛,质数筛打表(做一张已经打好的质数筛表封装在一个数组里)。这些常用的东西你虽然打多会增加熟练度提高你的码量,甚至可以让你成为首a人(第一个做出那题的人),但我觉得大可不必,真正到了生活中,封装的板子不仅能减少你的记忆量,甚至能给你脑子腾出更多的空间去存储其他算法(你可以理解为大脑作为指针存了地址,指向了书本上的内容)。
而优秀的代码往往是这样封装好的代码盒子,你吃透了这些代码盒子能变得更强,但前提是你有足够的时间去学习其他代码盒子。毕竟代码长路漫漫,不是只有算法是核心。

再讲一点有用的废话,while(t–)代替for(int i=1;i<=t;i++)前者是倒叙,后者是升序,这样的语句又清晰又不容易错,关键在于理解计算机的语法,所以学习语言先学习语法,再学习函数,这是亘古不变的。

while(t--)//从t=你输入的值,到t=1,当t=0时跳出循环(先执行循环)
for(int i=1;i<=t;i++)//此时i从1到t,i最后的结果会被自动清空,因为你的定义有且只在这个for循环语句内。(int规定的)

其他看我的代码大家自己吸收,对于大多数巨佬来说可能只是图一乐,但是更多的蒟蒻需要像我这样勇敢的人献出代码来变得更好。
以后如果有时间,我会陆续更新一些oj上大家能做的题解,来为大家变强贡献绵薄之力,毕竟所有有用的oj都有题解,我们这里因为成立时间太短而难以找到,这种事情得有人做,才会有更多的人做。

猜你喜欢

转载自blog.csdn.net/Crescent521/article/details/109953458