好久没写题解了,没办法,C站的题目更新的速度太慢了,重复考过去的老题已经不能再进步了。52期还混了个名次,总要写篇文章完成一下任务。而53期就惨了去了,三道选择题全蒙错了。

反正我个人觉得在现在C站的OJ环境里考选择题,真是出题人脑子被踢了。真要想拿满分太容易了:临时翻书这种笨方法就不提了,开赛后十分钟内出现的那么多0分选手还说明不了问题么?考完就能下载到正确答案,然后换个账户再进不就行了?对,我就是说给出题人听的,人家不是号称每期都复盘么?一个人复盘确实也有可能想不到这么多。:D

CSDN周赛52期及53期浅析-LMLPHP

当然,你也可以鄙视我,就当我吃不到葡萄说葡萄酸好了。:D


闲言少叙,说回编程题。毕竟这种题才更适合问哥这种没学过计算机专业的人。(本来历史就差,计算机历史就更别提了。)

52期的4道题目还是都考过:

投篮:27期考过,最长递增子数组。

买苹果:30期考过,纯模拟,题解在此。当然背包也能做(有点杀鸡用牛刀的感觉)。

打家劫舍:29期考过,题解在此。动态规划入门题,或者说递推题(类似斐波那契)。

天然气订单:30期、48期考过两回,题解在此,并查集。应该还有别的解法,不过问哥太懒,没空去试了。

这里面只有投篮没写过题解,但实在是太简单了:最长递增子数组,从头到尾遍历一遍答案就出来了。

然而赛后发现,还是有童鞋没有拿到满分。猜测可能是由于读题时错误地理解“得分清零”,认为每次都是从0开始计算。但实际上,从给的示例中就可以看出来,当球没有投进时,得分虽然清零了,但给出的数组里并没有记0,而是从下一个投进的球开始计分。也就是说,即使有连续几个球都投不进,也是不会出现在这个计分数组里的。 

这样一来,其实反而更简单了,因为不用去判断是否当前这个投球得分了。思路很简单:维护两个变量,一个是当前子数组的递增长度 temp,一个是最长的子数组长度,也就是答案 result。从头到尾遍历数组,如果当前数字(得分)比上一个数字大,则必然连续得分,temp 加一。反之,如果比上个数字小或相等,则必然这中间投篮失败,开始重新计分了,于是更新 result,再将 temp 重置为 1 (因为当前成功的投球也算一次)。循环结束时,还要记得再更新一次 result,因为有可能一直到最后都是递增的。

参考代码如下:

def solution(self, n, arr):
    temp = result = 1
    for i in range(1, n):
        if arr[i] > arr[i-1]:
            temp += 1
        else:
            result = max(temp, result)
            temp = 1
    return max(result, temp)

52期没什么可说的了,咱顺道说说53期。由于53期问哥选择题全错,砍掉30分,自然排不上名次了(而且不再是积分榜榜首了,终于治好了每期都参加的强迫症,哈哈),所以不会单独再写题解或文章。但是53期的两道编程题都是新题,虽然都是简单题。尤其是第2题等差数列,挺有意思的,有点脑筋急转弯的赶脚。问哥在此提供个思路,抛砖引玉,大家可以一起讨论。

这题乍看起来似乎有点不好下手,其实也非常简单。由等差数列的基本特性:相邻两个数字的差都相等(记为公差 d),可以轻松推导出:等差数列中任意两个数字的差都是这个公差 d 的倍数。 于是就可以得出结论:如果给出的数列可以组成等差数列(题目也是要求要尽可能组成等差数列)的话,其中已知的相邻数字的差的最大公约数 gcd,就是能构成等差数列的最大公差。

这里面有个特例,就是如果计算下来最大公约数是 0 的话,(0没有公约数,所以不能通过求最大公约数来得到 0,但是只要相邻数字的差是 0,就可以认为该数列最大公差是 0 了),如果首尾数字不相等的话,必然构成不了等差数列,答案是 NaN。而如果首尾数字相等,也不需要再添加任何数字了,因为这就是个由相同数字构成的“等差数列”,答案是 0。

得到最大公差后,要计算少了多少数字,就异常简单了:首尾相减,除去公差再加一,就得到这个数列的数字个数,减去给出数列的长度就是答案。

参考代码如下:

arr = sorted(map(int, input().split())) # 不确定给出的数列是否已经排好序,保险起见,先排序

d = arr[1] - arr[0]
if d > 0:
    from math import gcd
    for i in range(2, len(arr)):
        q = arr[i] - arr[i-1]
        if q == 0:
            d = 0
            break
        d = gcd(q, d)

if d == 0:
    if arr[0] == arr[-1]: print(0)
    else: print("NaN")
else: print((arr[-1]-arr[0])//q - len(arr) + 1)

当然,如果只给出了一个数字,答案是0,也算特例,但这里就没有考到了。

05-19 05:36