第十三届蓝桥杯省赛Python 组

这篇具有很好参考价值的文章主要介绍了第十三届蓝桥杯省赛Python 组。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

第十三届蓝桥杯省赛 Python B组

写在前面

本次所有代码均存放于仓库:

Github:GxlHus/Algorithm at 蓝桥杯 (github.com)

Gitee:Algorithm: 算法解题 - Gitee.com

原题目:第十三届蓝桥杯大赛软件赛省赛_PB.pdf · AYO/Algorithm - Gitee.com

本次省赛题目总体来说不难,总体质量比较高,尤其是后边几道题,虽然能轻易做出来,但是想跑通所有测试点,还得下功夫优化,做起来比较有意思,不像之前有些题做出来就满分,做不出来就毫无头绪,参与感不强。。

把自己的解题思路写在这里,也仅代表我个人理解得出的思路,不代表官方答案,欢迎大家交流,指正错误。

试题A:排列字母

本题总分:5 分

【问题描述】

小蓝要把一个字符串中的字母按其在字母表中的顺序排列。 例如,LANQIAO 排列后为 AAILNOQ。 又如,GOODGOODSTUDYDAYDAYUP 排列后为 AADDDDDGGOOOOPSTUUYYY
请问对于以下字符串,排列之后字符串是什么? WHERETHEREISAWILLTHEREISAWAY

【答案提交】

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个由大写字母组成的字符串,在提交答案时只填写这个字符串,填写多余的内 容将无法得分。


【思路分析】

这个没啥难的,Python直接转为listsorted即可,一行搞定

【完整代码】文章来源地址https://www.toymoban.com/news/detail-416504.html

s = 'WHERETHEREISAWILLTHEREISAWAY'
print(''.join(sorted(list(s))))

【参考答案】

AAAEEEEEEHHHIIILLRRRSSTTWWWY

试题B:寻找整数

本题总分:5 分

【问题描述】

有一个不超过 1 0 17 10^{17} 1017的正整数 n n n,知道这个数除以 2 2 2 49 49 49后的余数如下表 所示,求这个正整数最小是多少。

a n mod a a n mod a a n mod a a n mod a
2 1 14 11 26 23 38 37
3 2 15 14 27 20 39 23
4 1 16 9 28 25 40 9
5 4 17 0 29 16 41 1
6 5 18 11 30 29 42 11
7 4 19 18 31 27 43 11
8 1 20 9 32 25 44 33
9 2 21 11 33 11 45 29
10 9 22 11 34 17 46 15
11 0 23 15 35 4 47 5
12 5 24 17 36 29 48 41
13 10 25 9 37 22 49 46

【答案提交】

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。


【思路分析】

这个题思路很直,直接爆。但爆也有爆的技巧,可以先算一部分,然后得到一组符合条件的,作为步长,再筛选一轮,这样步长比较大的时候,列表中的数量较少,爆起来速度不至于太慢。

至于为什么不直接写大循环,因为我每次生成的范围和结果不一样,如果筛选后剩余的列表元素过多,需要将取余的范围加大,需要实时动态调整。

① 先给一个初值:

ls = [i for i in range(1, 10 ** 4)]

② 再进行一次筛选:

for i in range(2, 10):
    ls = list(filter(lambda x: x % i == mp[i], ls))

③ 然后进行一次输出:

[1649, 4169, 6689, 9209]

④ 然后以ls[0]作为初值,以ls[1]-ls[0]作为步长,再生成一组

ls = [i for i in range(ls[0], 10 ** 9, ls[1] - ls[0])]

⑤ 再筛选,这个筛选的范围不是固定的,10~20,~15都可以,但要根据上边的lsend值决定,如果太小,则筛选范围相应小一些,反之则大一些:

for i in range(10, 20):
    ls = list(filter(lambda x: x % i == mp[i], ls))

⑥ 输出:

[88209209, 321001769, 553794329, 786586889]

重复④⑤⑥执行

...

直到即得出最终结果

ls = [i for i in range(ls[0], 10 ** 17, ls[1] - ls[0])]
for i in range(30, 50):
    ls = list(filter(lambda x: x % i == mp[i], ls))
print(ls)

【完整代码】

mp = {2: 1, 3: 2, 4: 1, 5: 4, 6: 5, 7: 4, 8: 1, 9: 2, 10: 9, 11: 0, 12: 5, 13: 10, 14: 11, 15: 14, 16: 9, 17: 0, 18: 11,19: 18, 20: 9, 21: 11, 22: 11, 23: 15, 24: 17, 25: 9, 26: 23, 27: 20, 28: 25, 29: 16, 30: 29, 31: 27, 32: 25,33: 11, 34: 17, 35: 4, 36: 29, 37: 22, 38: 37, 39: 23, 40: 9, 41: 1, 42: 11, 43: 11, 44: 33, 45: 29, 46: 15, 47: 5, 48: 41, 49: 46}

ls = [i for i in range(1, 10 ** 4)]
for i in range(2, 10):
    ls = list(filter(lambda x: x % i == mp[i], ls))
print(ls)
ls = [i for i in range(ls[0], 10 ** 9, ls[1] - ls[0])]
for i in range(10, 20):
    ls = list(filter(lambda x: x % i == mp[i], ls))
print(ls)
ls = [i for i in range(ls[0], 10 ** 13, ls[1] - ls[0])]
for i in range(20, 30):
    ls = list(filter(lambda x: x % i == mp[i], ls))
print(ls)
ls = [i for i in range(ls[0], 10 ** 17, ls[1] - ls[0])]
for i in range(30, 50):
    ls = list(filter(lambda x: x % i == mp[i], ls))
print(ls)

【参考答案】

2022040920220409

试题C: 纸张尺寸

时间限制: 1.0s 内存限制: 512.0MB 本题总分:10 分

【问题描述】

在 ISO 国际标准中定义了 A0 纸张的大小为 1189 m m × 841 m m 1189mm × 841mm 1189mm×841mm,将 A 0 A0 A0纸沿长边对折后为 A 1 A1 A1纸,大小为 841 m m × 594 m m 841mm × 594mm 841mm×594mm,在对折的过程中长度直接取下整(实际裁剪时可能有损耗)。将 A 1 A1 A1
纸沿长边对折后为 A 2 A2 A2纸,依此类推。

输入纸张的名称,请输出纸张的大小。

【输入格式】

输入一行包含一个字符串表示纸张的名称,该名称一定是 A 0 A0 A0 A 1 A1 A1 A 2 A2 A2 A 3 A3 A3 A 4 A4 A4 A 5 A5 A5 A 6 A6 A6 A 7 A7 A7 A 8 A8 A8 A 9 A9 A9之一。

【输出格式】

输出两行,每行包含一个整数,依次表示长边和短边的长度。

【样例输入 1

A0

【样例输出 1

1189
841

【样例输入 2

A1

【样例输出 2

841
594

【思路分析】

这个题没啥难度,找到长边然后除以2就行。

注意一个坑:不是长宽同时除以2,而是长边。折叠之后长边会变成短边,所以要进行交换

【完整代码】

paper = input()
width = 1189
height = 841
count = int(paper[1])
while count > 0:
    if width < height:
        width, height = height, width
    width //= 2
    count -= 1
if width < height:
    width, height = height, width
print(width)
print(height)

试题D:数位排序

时间限制: 1.0s 内存限制: 512.0MB 本题总分:10 分

【问题描述】

小蓝对一个数的数位之和很感兴趣,今天他要按照数位之和给数排序。当两个数各个数位之和不同时,将数位和较小的排在前面,当数位之和相等时,将数值小的排在前面。

例如, 2022 2022 2022排在 409 409 409前面,因为 2022 2022 2022的数位之和是 6 6 6,小于 409 409 409的数位之和 13 13 13

又如, 6 6 6排在 2022 2022 2022前面,因为它们的数位之和相同,而 6 6 6小于 2022 2022 2022

给定正整数 n n n m m m,请问对 1 1 1 n n n采用这种方法排序时,排在第 m m m个的元素是多少?

【输入格式】

输入第一行包含一个正整数 n n n。第二行包含一个正整数 m m m

【输出格式】

输出一行包含一个整数,表示答案。

【样例输入】

13
5

【样例输出】

3

【样例说明】

1 1 1 13 13 13的排序为: 1 , 10 , 2 , 11 , 3 , 12 , 4 , 13 , 5 , 6 , 7 , 8 , 9 1, 10, 2, 11, 3, 12, 4, 13, 5, 6, 7, 8, 9 1,10,2,11,3,12,4,13,5,6,7,8,9。第 5 5 5个数为 3 3 3

【评测用例规模与约定】

对于 30 % 30\% 30%的评测用例, 1 ≤ m ≤ n ≤ 300 1 ≤ m ≤ n ≤ 300 1mn300

对于 50 % 50\% 50%的评测用例, 1 ≤ m ≤ n ≤ 1000 1 ≤ m ≤ n ≤ 1000 1mn1000

对于所有评测用例, 1 ≤ m ≤ n ≤ 106 1 ≤ m ≤ n ≤ 106 1mn106


【思路分析】

这个题也不难,首先是计算数位和,直接拆成列表,然后逐个取int(),再求列表的和即可

def swh(n):
    n = map(int, list(str(n)))
    return sum(n)

然后用字典生成式生成字典然后排序后按要求取值即可。

【完整代码】

def swh(n):
    n = map(int, list(str(n)))
    return sum(n)


def lst(end, start=1):
    ls = [i for i in range(start, end + 1)]
    sw = {i: swh(i) for i in ls}
    s = sorted(sw.items(), key=lambda x: x[1])
    return s


end = int(input())
i = int(input()) - 1
print(lst(end)[i][0])

试题E:蜂巢

时间限制: 1.0s 内存限制: 512.0MB 本题总分:15 分

【问题描述】

蜂巢由大量的六边形拼接而成,定义蜂巢中的方向为: 0 0 0表示正西方向, 1 1 1表示西偏北 60 ° 60° 60° 2 2 2表示东偏北 60 ° 60° 60° 3 3 3表示正东, 4 4 4表示东偏南 60 ° 60° 60° 5 5 5表示西偏南 60 ° 60° 60°

对于给定的一点 O O O,我们以 O O O为原点定义坐标系,如果一个点 A A A O O O点先向 d d d方向走 p p p步再向 ( d + 2 ) m o d 6 (d + 2) mod 6 (d+2)mod6方向( d d d的顺时针 120 ° 120° 120°方向)走 q q q步到达,则这个点的坐标定义为$(d; p; q)
。 在 蜂 窝 中 , 一 个 点 的 坐 标 可 能 有 多 种 。 下 图 给 出 了 点 。在蜂窝中,一个点的坐标可能有多种。下图给出了点 B(0; 5; 3) 和 点 和点 C(2; 3; 2)$的示意。

第十三届蓝桥杯省赛Python 组

给定点 ( d 1 , p 1 , q 1 ) (d_1, p_1, q_1) (d1,p1,q1)和点$(d_2, p_2, q_2),请问他们之间最少走多少步可以到达?

【输入格式】

输入一行包含 6 个整数 d 1 , p 1 , q 1 , d 2 , p 2 , q 2 d_1, p_1, q_1, d_2, p_2, q_2 d1,p1,q1,d2,p2,q2表示两个点的坐标,相邻两个整数之间使用一个空格分隔。

【输出格式】

输出一行包含一个整数表示两点之间最少走多少步可以到达。

【样例输入】

0 5 3 2 3 2

【样例输出】

7

【评测用例规模与约定】

对于 25 25% 25的评测用例, p 1 , p 2 ≤ 103 p1, p2 ≤ 103 p1,p2103

对于 50 50% 50的评测用例, p 1 , p 2 ≤ 105 p1, p2 ≤ 105 p1,p2105

对于 75 75% 75的评测用例, p 1 , p 2 ≤ 107 p1, p2 ≤ 107 p1,p2107

对于所有评测用例, 0 ≤ d 1 , d 2 ≤ 5 , 0 ≤ q 1 < p 1 ≤ 109 , 0 ≤ q 2 < p 2 ≤ 109 0 ≤ d1, d2 ≤ 5,0 ≤ q1 < p1 ≤ 109,0 ≤ q2 < p2 ≤ 109 0d1,d250q1<p11090q2<p2109


【思路分析】

这个题,我不会,但我觉得,将路径看成三角形,已知角度,已知两边和,求出第三边的长,然后得到两点的斜边长,然后再根据夹角算两边的长度。

但是我也不知道对不对,说来惭愧,鄙人三角形学的非常辣鸡,不知道怎么求非直角三角形的第三边长,所以只有这么个想法,并没有实现。。。

如果思路不对,还请大佬赐教,如果思路对的话,麻烦大佬实现😂

试题F:消除游戏

时间限制: 3.0s 内存限制: 512.0MB 本题总分:15 分

【问题描述】

在一个字符串 S S S中,如果 S i = S i − 1 S_i = S_{i−1} Si=Si1 S i ∗ S i ₊ 1 S_i * S_{i₊1} SiSi1,则称 S i S_i Si S i ₊ 1 S_{i₊1} Si1为边缘字符。如果 S i ∗ S i − 1 S_i * S_{i−1} SiSi1 S i = S i ₊ 1 S_i = S_{i₊1} Si=Si1,则 S i − 1 S_ {i−1} Si1 S i S_i Si也称为边缘字符。其它的字符都不是边缘字符。

对于一个给定的串 S S S,一次操作可以一次性删除该串中的所有边缘字符(操作后可能产生新的边缘字符)。

请问经过 2 64 2^{64} 264次操作后,字符串 S S S变成了怎样的字符串,如果结果为空则输出 EMPTY

【输入格式】

输入一行包含一个字符串 S 。

【输出格式】

输出一行包含一个字符串表示答案,如果结果为空则输出 EMPTY

【样例输入 1】

edda

【样例输出 1】

EMPTY

【样例输入 2】

sdfhhhhcvhhxcxnnnnshh

【样例输出 2】

s

【评测用例规模与约定】

对于 25 25% 25的评测用例, ∣ S ∣ ≤ 1 0 3 |S | ≤ 10^3 S103,其中 ∣ S ∣ |S | S表示 S S S的长度;对于 50 50% 50的评测用例, ∣ S ∣ ≤ 1 0 3 |S | ≤ 10^3 S103

对于 75 75% 75的评测用例, ∣ S ∣ ≤ 1 0 3 |S | ≤ 10^3 S103

对于所有评测用例, ∣ S ∣ ≤ 1 0 6 |S | ≤ 10^6 S106 S S S中仅含小写字母。


【思路分析】

这个题没有好的思路,只能暴力模拟了😂

需要留意几个地方:

  • 不能直接删除项目中边缘字符,如果直接删除会导致越界
  • 也不能直接将待删除的边缘字符替换成其他字符,因为这样会导致判断出问题,比如xxvxv待删除,将其替换为0,变为x00,则执行下一步的时候就会将x0作为边缘字符删掉x
  • 其实循环不了 2 64 2^{64} 264次,如果化到最简,则可以比较处理前和处理后的结果,如果相同,则已经是最简了,直接跳出循环即可

两个解决办法,一个是先判断逆向字符,比如xxv,再判断正向字符:xvv

另一个是使用一个集合将待删除的下标保存,然后循环结束后统一删除。

【完整代码】

def remove_edge():
    global s
    rm = set()
    for i in range(1, len(s) - 1):
        if s[i] == s[i + 1] and s[i - 1] != s[i]:
            rm.add(i - 1)
            rm.add(i)
        if s[i] == s[i - 1] and s[i] != s[i + 1]:
            rm.add(i)
            rm.add(i + 1)
    for i in rm:
        s[i] = ''
    s = list(''.join(s))


s = list(input())
for i in range(2 ** 64):
    ls = s
    remove_edge()
    if ls == s:
        print(''.join(s))
        break
    if len(s) == 0:
        print('EMPTY')
        break
else:
    print(''.join(s))

试题G:全排列的价值

时间限制: 1.0s 内存限制: 512.0MB 本题总分:20 分

【问题描述】

对于一个排列 A = ( a 1 , a 2 , . . . , a n ) A = (a_1, a_2,..., a_n) A=(a1,a2,...,an),定义价值 c i c_i ci a 1 a_1 a1 a i − 1 a_{i-1} ai1中小于 a i a_i ai的数的个数,即 b i = ∣ { a j ∣ j < i , a j < a i } ∣ b_i = |\{a_j| j < i, a_j < a_i\}| bi={ajj<i,aj<ai}。定义
A A A的价值为 ∑ i = 1 n c i \sum^n_{i=1}c_i i=1nci

给定 n n n,求 1 1 1 n n n的全排列中所有排列的价值之和。

【输入格式】

输入一行包含一个整数 n n n

【输出格式】

输出一行包含一个整数表示答案,由于所有排列的价值之和可能很大,请输出这个数除以 998244353 998244353 998244353的余数。

【样例输入 1】

3

【样例输出 1】

9

【样例输入 2】

2022

【样例输出 2】

593300958

【样例说明】

1 至 3 构成的所有排列的价值如下:

(1, 2, 3) : 0 + 1 + 2 = 3 ;
(1, 3, 2) : 0 + 1 + 1 = 2 ;
(2, 1, 3) : 0 + 0 + 2 = 2 ;
(2, 3, 1) : 0 + 1 + 0 = 1 ;
(3, 1, 2) : 0 + 0 + 1 = 1 ;
(3, 2, 1) : 0 + 0 + 0 = 0 ;

故总和为 3 + 2 + 2 + 1 + 1 = 9 3 + 2 + 2 + 1 + 1 = 9 3+2+2+1+1=9

【评测用例规模与约定】

对于 40 % 40\% 40%的评测用例, n ≤ 20 n ≤ 20 n20

对于 70 % 70\% 70%的评测用例, n ≤ 5000 n ≤ 5000 n5000;对于所有评测用例, 2 ≤ n ≤ 1 0 6 2 ≤ n ≤ 10^6 2n106


【思路分析】

这道题比较有意思,暴力肯定不行。

首先,试想一下, 2 2 2 1 1 1的价值,只有在 [ 1 , 2 ] [1, 2] [1,2]的情况下才有价值为1.

在(1, 2, 3)的组合里边,2在1前边有三种情况,分别是:

(1, 2, 3)
(1, 3, 2)
(3, 1, 2)

这三种的情况,也就是2产生的值为3*1,然后再考虑3的位置和价值,3是当前组合里边最大的数,当3置于最后边,可以产生的价值为:2*2,当3的价值置于中间,所产生的价值为1*2

所以(1, 2, 3)全排列的值为: 3 ∗ 1 + 2 ∗ 2 + 1 ∗ 2 3*1+2*2+1*2 31+22+12。数据量太小,还看不出什么规律。我们再做一下(1, 2, 3, 4)的排列。

首先(1, 2, 3)的全排列为9,然后有4个位置可以插入4,所以(1, 2, 3, 4)的全排列中,(1, 2, 3)产生的价值为: 9 ∗ 4 = 36 9*4=36 94=36,当4置于末尾时,(1, 2, 3)
每一种排列方式都能给4带来3的价值,所以即当4置于末尾时即为 3 ∗ A 3 3 3*A_3^3 3A33,当4置于第3位,则(1, 2, 3)每一种排列,都能给4带来2的价值,即为 3 ∗ A 2 2 3*A_2^2 3A22。然后是第二位…第一位…

由此可以推得,某一位数的全排列值,等于他本身乘以前一个数的全排列值,然后再加上 ∑ i = 1 n − 1 i A n − 1 n − 1 \sum_{i=1}^{n-1}iA_{n-1}^{n-1} i=1n1iAn1n1 A n n A_n^n Ann n ! n! n!,即可得公式

c n = n ∗ ( n − 1 ) + ∑ i = 1 n − 1 i ∗ ( n − 1 ) ! c_n=n*(n-1)+\sum_{i=1}^{n-1}i*(n-1)! cn=n(n1)+i=1n1i(n1)!

∑ i = 1 n − 1 i ∗ ( n − 1 ) ! \sum_{i=1}^{n-1}i*(n-1)! i=1n1i(n1)!可以进一步化简为 ( n − 1 ) ∗ ( 1 + n − 1 ) 2 ∗ ( n − 1 ) ! \frac{(n-1)*(1+n-1)}{2}*(n-1)! 2(n1)(1+n1)(n1)!,即 ( n − 1 ) ∗ n 2 ∗ ( n − 1 ) ! \frac{(n-1)*n}{2}*(n-1)! 2(n1)n(n1)!

故可以得出递归函数

@functools.lru_cache(10 ** 6)
def get_value(n):
    m = n - 1
    jcc = jc(m) # jc(),自定义函数,求阶乘
    v = m * n // 2
    return (n * get_value(n - 1) + jcc * v) % 998244353
  • 这个递归很好理解,但是实际跑的时候数据稍大就会栈溢出,所以得给他改成循环。
  • 这里阶乘要用自定义函数加缓存,因为每一个数得价值,都会求一次阶乘,反复求的话自定义的函数加缓存在效率上相比于math.factorial()提升会非常明显,例如样例的2022,缓存求递归仅需要0.01s
    ,而用math.factorial()则需要0.1s
  • 跑了一下, 5000 5000 5000没啥问题,能过 70 % 70\% 70%的样例,但是跑不了 1 0 6 10^6 106,估计把阶乘的求法再优化优化能跑通

【完整代码】

import functools
import math


@functools.lru_cache(10 ** 6)
def jc(n):
    if n <= 1:
        return 1
    return n * jc(n - 1)


n = int(input())
v = [0, 1]
for i in range(1, n + 1):
    m = i - 1
    jcc = jc(m)
    l = (m * i) // 2
    v[1] = ((v[0] * i + l * jcc) % 998244353)
    v[0] = v[1]
print(v[1])

试题H:技能升级

时间限制: 1.0s 内存限制: 512.0MB 本题总分:20 分

【问题描述】

小蓝最近正在玩一款 RPG 游戏。他的角色一共有 N 个可以加攻击力的技能。其中第 i 个技能首次升级可以提升 A i A_i Ai点攻击力,以后每次升级增加的点数都会减少 B i B_i Bi ⌈ A i ⌉ ⌈ Ai ⌉ Ai(上取整)

次之后,再升级该技能将不会改变攻击力。

现在小蓝可以总计升级 M 次技能,他可以任意选择升级的技能和次数。请你计算小蓝最多可以提高多少点攻击力?

【输入格式】

输入第一行包含两个整数 N N N M M M。 以下 N N N行每行包含两个整数 A i A_i Ai B i B_i Bi

【输出格式】

输出一行包含一个整数表示答案。

【样例输入】

3 6
10 5
9 2
8 1

【样例输出】

47

【评测用例规模与约定】

对于 40 % 40\% 40%的评测用例, 1 ≤ N , M ≤ 1000 1 ≤ N, M ≤ 1000 1N,M1000

对于 60 % 60\% 60%的评测用例, 1 ≤ N ≤ 1 0 4 , 1 ≤ M ≤ 1 0 7 1 ≤ N ≤ 10^4, 1 ≤ M ≤ 10^7 1N104,1M107

对于所有评测用例, 1 ≤ N ≤ 1 0 5 , 1 ≤ M ≤ 2 × 1 0 5 , 1 ≤ A i , B i ≤ 1 0 5 1 ≤ N ≤ 10^5,1 ≤ M ≤ 2 × 10^5,1 ≤ Ai, Bi ≤ 10^5 1N1051M2×1051Ai,Bi105


【思路分析】

这个第一想法就是直接列表,降序,加攻击,减去攻击加成,再降序…

简单的不像20分的题,,因为前一题推了将近1个小时,怕后边时间不够,所以尽管潜意识觉得有坑,但还是没有深究

【完整代码】

n, m = map(int, input().split())
add = []
ans = 0
for i in range(n):
    a, b = map(int, input().split())
    add.append([a, b])
while m > 0:
    add = sorted(add, key=lambda x: x[0], reverse=True)
    ans += add[0][0]
    add[0][0] -= add[0][1]
    m -= 1
print(ans)

试题I: 最长不下降子序列

时间限制: 1.0s 内存限制: 512.0MB 本题总分:25 分

【问题描述】

给定一个长度为 N 的整数序列: A ₁ , A ₂ , ⋅ ⋅ ⋅ , A N A₁, A₂, · · · , AN A,A,,AN。现在你有一次机会,将其中连续的 K K K

个数修改成任意一个相同值。请你计算如何修改可以使修改后的数列的最长不下降子序列最长,请输出这个最长的长度。

最长不下降子序列是指序列中的一个子序列,子序列中的每个数不小于在它之前的数。

【输入格式】

输入第一行包含两个整数 N N N K K K。 第二行包含 N N N个整数 A ₁ , A ₂ , ⋅ ⋅ ⋅ , A N A₁, A₂, · · · , A_N A,A,,AN

【输出格式】

输出一行包含一个整数表示答案。

【样例输入】

5 1
1 4 2 8 5

【样例输出】

4

【评测用例规模与约定】

对于 20% 的评测用例, 1 ≤ K ≤ N ≤ 100 1 ≤ K ≤ N ≤ 100 1KN100;对于 30% 的评测用例, 1 ≤ K ≤ N ≤ 1000 1 ≤ K ≤ N ≤ 1000 1KN1000

对于 50% 的评测用例, 1 ≤ K ≤ N ≤ 10000 1 ≤ K ≤ N ≤ 10000 1KN10000

对于所有评测用例, 1 ≤ K ≤ N ≤ 10 ⁵ , 1 ≤ A i ≤ 10 ⁶ 1 ≤ K ≤ N ≤ 10⁵,1 ≤ Ai ≤ 10⁶ 1KN101Ai10


【思路分析】

这个题,没想到好的思路,只有硬干。。。根据题目描述一行一行写…两层没优化的循环,复杂度 O ( n 2 ) O(n^2) O(n2),不指望能跑通了

【完整代码】

import copy


# 判断非递减
def isfdj(lst):
    return lst == sorted(lst)


n, k = map(int, input().split())
ls = list(map(int, input().split()))
l = []
for i in range(1, n - k):
    tmp = copy.deepcopy(ls)
    t = ls[i - 1]
    for j in range(i, i + k):
        tmp[j] = t
    ll = 0 # 当前子串长度
    low = 0
    high = 1
    while high < n:
        if isfdj(tmp[low:high]):
            ll += 1
        else:
            l.append(ll)
            ll = 0
            low = high
        high += 1
    l.append(ll)
print(max(l))

试题J: 最优清零方案

时间限制: 5.0s 内存限制: 512.0MB 本题总分:25 分

【问题描述】

给定一个长度为 N N N的数列 A ₁ , A ₂ , ⋅ ⋅ ⋅ , A N A₁, A₂, · · · , A_N A,A,,AN。现在小蓝想通过若干次操作将这个数列中每个数字清零。

每次操作小蓝可以选择以下两种之一:

  1. 选择一个大于 0 0 0的整数,将它减去 1 1 1
  2. 选择连续 K K K个大于 0 0 0的整数,将它们各减去 1 1 1。小蓝最少经过几次操作可以将整个数列清零?

【输入格式】

输入第一行包含两个整数 N N N K K K

第二行包含 N N N个整数 A ₁ , A ₂ , ⋅ ⋅ ⋅ , A N A₁, A₂, · · · , A_N A,A,,AN

【输出格式】

输出一个整数表示答案。

【样例输入】

4 2
1 2 3 4

【样例输出】

6

【评测用例规模与约定】

对于 20 % 20\% 20%的评测用例, 1 ≤ K ≤ N ≤ 10 1 ≤ K ≤ N ≤ 10 1KN10

对于 40 % 40\% 40%的评测用例, 1 ≤ K ≤ N ≤ 100 1 ≤ K ≤ N ≤ 100 1KN100

对于 50 % 50\% 50%的评测用例, 1 ≤ K ≤ N ≤ 1000 1 ≤ K ≤ N ≤ 1000 1KN1000

对于 60 % 60\% 60%的评测用例, 1 ≤ K ≤ N ≤ 10000 1 ≤ K ≤ N ≤ 10000 1KN10000

对于 70 % 70\% 70%的评测用例, 1 ≤ K ≤ N ≤ 100000 1 ≤ K ≤ N ≤ 100000 1KN100000

对于所有评测用例, 1 ≤ K ≤ N ≤ 1000000 , 0 ≤ A i ≤ 1000000 1 ≤ K ≤ N ≤ 1000000, 0 ≤ A_i ≤ 1000000 1KN1000000,0Ai1000000


【思路分析】

这个题就没啥好分析的了,甚至暴力模拟都没想好怎么模拟,直接用了贪心,从前往后挨个减一遍。猜着应该要用动规,但没想出来怎么个规法。分享下自己的残缺代码,也欢迎大佬赐教。

【完整代码】

n, k = map(int, input().split())
lst = list(map(int, input().split()))
red = lambda x: x - 1
i = 0
c = 0
while True:
    r = i + k
    if r <= n:
        if 0 not in lst[i:r]:
            lst[i: r] = map(red, lst[i:r])
            c += 1
        else:
            i = lst[i: r].index(0) + i + 1
    else:
        break
c += sum(lst)
print(c)

到了这里,关于第十三届蓝桥杯省赛Python 组的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【十三届蓝桥杯省赛解析javaC组】

    题目描述 解题思路 A题相对比较简单,这题有两种解法 第一种是可以利用记事本把文本复制,然后自己手动排序 第二种是写代码:具体思路是定义一个字符串用来储存问文本,然后把文本转成字符型数组,利用Arrays.sort对字符型数组进行排序,最终实现字符的排序 代码示例

    2023年04月20日
    浏览(39)
  • 6 -【第十三届】蓝桥杯物联网试题 (省赛题)

    1.将时钟树频率设置成32MHz 2.将GPIO引脚做如下配置: 引脚功能 使能中断 打开串口通信2 3.生成工程代码 4.移植OLED、LoRa库文件 5.编写逻辑代码 Task_Main.h Task_Main.c stm32l0xx_it.c main.c 1.将时钟树频率设置成32MHz 2.将GPIO引脚做如下配置: 引脚功能 使能中断 3.生成工程代码 4.移植LoRa、

    2023年04月08日
    浏览(68)
  • 蓝桥杯单片机学习14——第十三届省赛题

    上期我们学习了NE555方波发生器频率测量,讲到我会更新之后省赛的题目,那么,他来了。 首先声明:我还没有参加蓝桥杯单片机比赛,也没有拿过奖,所以我写的代码注定不会那么完美,存在BUG是必然的,我写这个系列的目的纯粹是为了记录我的学习………… 关于功能描述

    2024年02月06日
    浏览(52)
  • 第十三届省赛蓝桥杯物联网程序设计试题

    1、配置根据试题的要求配置STM32CubeMX (1)引脚配置 将PC14引脚配置为输入模式 PC14 用户按键引脚 将PA10引脚配置为中断模式 PA10 LoRa模块DIO0引脚 将以下引脚配置为输出模式 PC15 用户LED引脚 PB5 OLED 电源控制引脚 PA11和PA12 继电器控制引脚 PA4和PA9 LoRa模块片选和复位引脚,初始为高电

    2023年04月10日
    浏览(48)
  • 【蓝桥杯Web】第十三届蓝桥杯(Web 应用开发)省赛真题

    第十三届蓝桥杯全国软件和信息技术专业人才大赛(软件类)新开了Web应用开发比赛,本文介绍第十三届蓝桥杯Web应用开发的省赛题目以及解析。 题目描述:使用Flex属性快速完成布局。 题目分析:主要涉及的是Flex弹性布局的知识,主要包括主轴方向和是否换行。 题目代码:

    2023年04月10日
    浏览(46)
  • 第十三届蓝桥杯大赛软件赛省赛(C++研究生组)

    可以证明,只要首先裁剪最外围的 4 4 4 条边,之后无论怎样裁剪,次数都是最少。对于 n n n 行 m m m 列的二维码,至少需要裁剪 n m + 3 nm + 3 nm + 3 次,因此答案为 20 × 22 + 3 = 443 20times 22+3=443 20 × 22 + 3 = 443 。 证明:只需证明裁掉边界后至少还需裁剪 n m − 1 nm-1 nm − 1 次。 n

    2023年04月10日
    浏览(42)
  • 【蓝桥杯嵌入式】第十三届蓝桥杯嵌入式省赛客观题以及详细题解

    题解:   概念题。 MCO引脚,是单片机对外提供时钟的引脚。 HSE,高速外部时钟信号,时钟源由外部晶体/陶瓷谐振器与外部时钟; HSI,高速的内部时钟,由内部8MHz的RC振荡器产生,可直接作为系统时钟或在2分频后作为PLL输入; SYSCLK,是系统时钟; HSE/2,对高速外部时钟进

    2023年04月16日
    浏览(139)
  • 第十三届蓝桥杯 Java C组省赛 C 题——纸张尺寸(AC)

    在 ISO 国际标准中定义了 A0 纸张的大小为 1189mm × 841mm, 将 A0 纸 沿长边对折后为 A1 纸, 大小为 841mm × 594mm, 在对折的过程中长度直接取 下整 (实际裁剪时可能有损耗)。将 A1 纸沿长边对折后为 A2 纸, 依此类推。 输入纸张的名称, 请输出纸张的大小。 输入一行包含一个字符串表示

    2024年02月11日
    浏览(39)
  • 第十三届蓝桥杯 C++ B组省赛 C 题——刷题统计(AC)

    小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天 做 a a a 道题目, 周六和周日每天做 b b b 道题目。请你帮小明计算, 按照计划他将在 第几天实现做题数大于等于 n n n 题? 输入一行包含三个整数 a , b a,b a , b 和 n n n . 输出一个整数代表天数。 10 20 99 8 1 ≤

    2024年01月20日
    浏览(35)
  • 第十三届蓝桥杯 Java B 组省赛 D 题—— 最少刷题数(AC)

    小蓝老师教的编程课有 N N N 名学生, 编号依次是 1 … N 1…N 1 … N 。第 i i i 号学生这学期 刷题的数量是 A i A_{i} A i ​ 。 对于每一名学生, 请你计算他至少还要再刷多少道题, 才能使得全班刷题 比他多的学生数不超过刷题比他少的学生数。 第一行包含一个正整数 N N N 。 第二

    2023年04月09日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包