150 likes | 342 Views
第四次习题讲解. 数组. 1.oreoandjc. 题目大意:找出一个存放在数组中的数列,所有最大元素的下标。 时空限制:1s && 32MB 注:这里的时空限制有一个大约的概念,1s相当于做10^8 数量级的加法运算,而32MB相当于 800W的int 变量。 而观察数据范围N<=3000 说明这个程序能接受n^2及以下的时间复杂度. 1.oreoandjc. 0<=ai<2^31 告诉我们 ai的数据范围很大 但是不超过int。 遍历一遍数组能做到求出最大元素是哪一个·· ,而要求下标分别是多少只要再遍历一遍,遇到与最大元素相同的直接输出就行
E N D
第四次习题讲解 数组
1.oreoandjc • 题目大意:找出一个存放在数组中的数列,所有最大元素的下标。 • 时空限制:1s && 32MB • 注:这里的时空限制有一个大约的概念,1s相当于做10^8 数量级的加法运算,而32MB相当于 800W的int 变量。 • 而观察数据范围N<=3000 说明这个程序能接受n^2及以下的时间复杂度
1.oreoandjc • 0<=ai<2^31 告诉我们 ai的数据范围很大 但是不超过int。 • 遍历一遍数组能做到求出最大元素是哪一个·· ,而要求下标分别是多少只要再遍历一遍,遇到与最大元素相同的直接输出就行 • 而如果这样做的话 时间复杂度只有O(n) • 空间复杂度也只有O(n) • 都可以接受 于是编程实现就可以了>_<
5.Books • 题意:求出所有含有"555"字符子串的原串个数,并输出。 • 时空限制:1s && xxxMB(内存限制似乎后面有改动) • 从刚才的备注可以知道,在32MB的内存限制是可以开下char s[1005][1005]的 但是很多这样做的同学却出现SO的情况。
5.Books • 原因在于,开char s[1005][1005]的同学都开的是局部变量,而编译器在用到局部变量的时候调用的是系统内部栈的空间,而这个空间不允许超过xxxxx(不同的平台不一样)所以出现了SO(stack overflow)的情况。 • 因此只要开到全局变量中就可以了。另:如果一定要开局部变量,请参考如何手动开大栈空间--google之- -|||
5.Books • 另:字符串的读入·· 强烈推荐在没有空格存在的时候用scanf("%s",str)读入,在有空格的时候用gets(str)读入,用scanf("%c",&str[i])之类的比较容易出问题,这次有好多同学在某个点一直过不去出现WA,有一些是读入的问题- - • 另外一些的话,我只能说某些小细节或者是RP不够导致,但也不排除可能是数据有问题,毕竟是随机出来的,但是过的人也不少>_<
5.Books • 思路:比较好想就是如果某一位出现了5,str[i]=='5' 检查他的下一位和再下一位str[i+1]=='5' && str[i+2]=='5' 如果是的话就ans++,然后调出循环,读入下一个。(这道题目可以一边读一边做,做完一个再读入一个) • 另:这一题没有track我是好人不设track有track也是小track。
7.conspiracy • 题意:找出某一行与某一列之和的最大,并输出行标和列标。 • 时空限制:1s && 似乎不到32MB(我交MLE一次T T) • 首先说下做法(1),先把这些数都存下来,然后遍历二维数组,遇到一个数去求和他同一行或者和他同一列的数字之和,这样写的话将会是一个O(n^3)的做法,其实也可以过,但是很卡时间。也没有充分考虑优化。
7.conspiracy • 但是我们考虑一下就可以知道,我们求与某个数同行或同列的所有数(包括把本身)可以这样算:row[i]+lin[j]-a[i][j] ,row表示的就是与这个数同一行所有数的和,lin表示与这个数同一列所有数字的和。 • 更重要的是,我们在读入的O(n^2)复杂度中就可以把所有的row[i]与lin[j]算出来。 • 例如我读入一个a[i][j],这时候我只要
7.conspirac • row[i]+=a[i][j],lin[j]+=a[i][j],可以理解为这个a[i][j]属于第i行第j列,因此将统计第i行数字总和的row[i]加上属于这一行的a[i][j]。而对于列同理。 • 因此到最后我们在枚举a[i][j]的时候就可以通过公式row[i]+lin[j]-a[i][j]在O(1)的时间求出与a[i][j]同行或同列的所有数的和。 • 而时间复杂度也将是O(n^2)
8.walking • 题意:就是按某种方式走过一些带权格子,按走过路径进行某种计算。这个不是很好描述啊·· 但是题目应该都看过的,所以没关系XD • 时空限制 1s && 32MB • 这题本来是想出个模拟题··· 但是啊但是啊,这题目是有性质的。 • 我先说模拟解法,就是用3个变量,表示当前状态,所在行xi,所在列yi,面朝方向di
8.walking • 初始位置xi=0,yi=0,di=0 (0向右,1向下,2向左,3向上),根据di,模拟每一步的走法,如di==0 时 下一步就是xi,yi+1。di==1时 下一步是 xi+1,yi其余同理。 • 要注意的是一旦走到边界,或者下一步是已经走过的格子,就要考虑转向问题转向的话因为我们的di设定可以直接写为(di+1)%4,直接用if判断也可以。
8.walking • 然后用下一步的减去前一步的值加入ans,终止的条件是走到某一个点,无法再走一步,就可以跳出循环输出答案了。 • 而这道题目,是有数学解法的- -Orz • 回忆一下高中时候老师叫求 • 1/2+1/6+1/12+......1/(n*(n+1))是怎么求的?
8.walking • 原式=1-1/2+1/2-1/3+1/3-........=1-1/(1+n)=n/(n+1) • 然后这题同理·· 只要求出终点的i,j就可以直接得出答案·· 时间的话 只有读入的时间 虽然与模拟的做法一样最终趋近都是O(n^2)但是明显更优。 • 而最终的格子是哪个?你们可以去推下·· 我也有在ppt的注释中放出两种标程- -
8.walking Xi=0 Yi=0 Di=0 Xi=0 Yi=1 Di=0 Xi=0 Yi=5 Di=0 Xi=1 Yi=5 Di=1