蓝桥杯Python b组 个人复习笔记(week1)

个人总结:

一周以来,目前已简单复习了真题里的填空题,二分,暴力枚举(EZ),前缀和与差分(预计周末继续刷题巩固巩固),于此记录,以备考前复习,并与各位交流增进。(致赛前一周左右回来复习的自己:自己不止刷了这点题,公共课上多看多复习,不会就学,菜就多练,以前你会那是以前,现在你不会那就是不会,那就多练),事先声明,刷题过程中遇到的难题怪题不会出现在本文之中各位萌新放心食用,各位大佬轻喷(自己也别忘了看自己写的纸质笔记orz)

填空题真题:

这里没有特别需要注意的知识点,需要注意的是到时候比赛时允许使用Excel与WORD,个别DFS迷宫题(有一道真题题目名好像就叫迷宫)由于数据过小可以直接使用手数得出结果,如果一定要编码,需要注意的是通常会因为数据量过大而导致运行时间过长,一定要对自己有信心,不要怀疑自己;

这里附上个人挑选的两道题目:

门牌制作:
# 题目要求本质上就是要求 1~2020的2的个数,编码时直接暴力枚举即可
n = ''
for i in range(1,2021):
    n += str(i)
    print(n.count('2'))

# 但实际上有更简单的方法,我们可以直接打印出来1~2020,然后将他们复制到WORD中直接查找即可!
不包含2023:
# 完全不包含2023
def judge(x):
    # 定义需要排除的数字
    li = [3, 2, 0, 2]
    i = 0
    while x > 0:
        t = x % 10
        x //= 10
        if t == li[i]:
            i += 1
        if i == 4:
            return 0  # 如果匹配到了完全不包含的数字2023,则返回0
    return 1  # 如果没有匹配到,则返回1

if __name__ == '__main__':
    st = 12345678  # 起始值
    ed = 98765432  # 结束值
    res = 0
    for x in range(st, ed+1):
        res += judge(x)  # 调用judge函数,统计不包含2023的数字个数
    print(res)  # 输出结果:85959030

二分:

复习二分法时,我更多的是在刷洛谷题单上的题,首先我们需要明晰二分法的核心是什么?我认为最核心的地方就在于与中间值比较,然后不断进行夹逼,最后寻找到结果(注意一定要是一个有序的序列,别问为啥要强调这个,都是泪啊QAQ)。然后对于Python来说,提供了内置库bisect实现二分算法,有余力者可以学习,可以大幅减少代码量(不过不学也没关系,重在理解算法思想!!!!!)

下面我先附上一道洛谷上的模板题:

P2249 【深基13.例1】查找

import bisect
    
n,m = input().split()
li = list(map(int, input().split())) # nums 数据集
target = list(map(int, input().split())) # 查找对象
li.sort()  # 对li进行原地排序

for i in target:
    position = bisect.bisect_left(li, i)
    if position < len(li) and li[position] == i:
        print(position+1, end=' ')
    else:
        print(-1, end=' ')

后面是两道当时对我来说启发非常大的题目:(致赛前一周左右回来复习的我:如果你忘了二分,一定给自己俩大比兜,然后做做这两道题)

P1102 A-B 数对

import bisect

# 输入N和C
N, C = map(int, input().split())

# 输入原始列表li
li = list(map(int, input().split()))
li.sort()  # 对li进行原地排序

# 创建新列表li1,将li中的每个元素减去C,得到新的列表li1
li1 = [0] * N  # 创建长度为N的列表li1
for i in range(N):
    li1[i] = li[i] - C

count = 0
for i in range(N):
    # 使用bisect.bisect_left()和bisect.bisect_right()函数获取li1[i]在li中的插入位置
    x = bisect.bisect_left(li, li1[i])
    y = bisect.bisect_right(li, li1[i])
    count += y - x  # 计算目标范围内的数量,使用y - x来得到范围内的元素数量

print(count)  # 输出最终的计数结果

P1024 [NOIP2001 提高组] 一元三次方程求解

n = input().split()  
cnt = 0
def func(x,n):
    a,b,c,d = eval(n[0]),eval(n[1]),eval(n[2]),eval(n[3])
    return (((a*x+b)*x)+c)*x+d
    
for i in range(-100,100):
    l = i
    r = i+1
    x1 = func(i,n)
    x2 = func(i+1,n)
    if x1 == 0:
        print("{:.2f}".format(l),end=" ")
        cnt += 1
    if x1*x2<0 :#大前提:左边和右边都不为0
        while (r-l) >= 0.001:#精度为两位小数故取三位小数可以夹逼至(l、r)最相近就可以近似的看作l==r;故只打印r
            m = (l+r)/2
            if func(m,n)*func(r,n) <= 0:
                l = m
            else:
                r = m
        print("{:.2f}".format(r),end=" ")
        cnt += 1
    if cnt == 3:
        break

暴力枚举

这里我附上一个我这一周来刷题经常看的博客,作者风趣幽默,题目总结的也很全面供学习参考https://blog.csdn.net/m0_55148406/article/details/123385812

这里我附上我做的题中的几道洛谷题(推荐大家还是刷刷洛谷题单里的题,有的真的很拓宽思路):

P2241 统计方形(数据加强版)

n, m = map(int, input().split())
if n > m:
    n,m = m,n

a = int((n*(n+1)/2)*(m*(m+1)/2))
x,y = 0,0
for i in range(1, n+1):
    x += (n-i+1)*(m-i+1)
print(x, a-x)

P2089 烤鸡(PS:全是他喵的枚举,真的很无趣的一题,但是做做还是会很强化自己的基本功的)

n = int(input())
if n> 30 or n < 10:
    print(0)
else:
    ls = []
    for a in range(1,4):
        for b in range(1,4):
            for c in range(1,4):
                for d in range(1,4):
                    for e in range(1,4):
                        for f in range(1,4):
                            for g in range(1,4):
                                for h in range(1,4):
                                    for i in range(1,4):
                                        for j in range(1, 4):
                                            if a+b+c+d+e+f+g+h+i+j==n:
                                                ls.append([str(a),str(b),str(c),str(d),str(e),str(f),str(g),str(h),str(i),str(j)])
    print(len(ls))
    for x in ls:
        print(' '.join(x))
#当时我写完后我都怀疑这题出出来,作者是不是就是为了考验我的毅力了23333

前缀和

最后这里浅浅说一下前缀和吧,差分算法打算周末刷刷再巩固一下

前缀和算法主要的应用场景在于某段区间求和的问题中:我认为他的他的核心步骤在于三点:

1: 确定列表数据以及数据范围

2:确定求和区间,建立dp序列

3:最后直接迭代dp序列进行取值

这里附上算法模板:

#线性DP-前缀和模板
for i in range(1,n+1):
   dp[i]=dp[i-1]+a[i]
print(dp[r]-dp[l-1])
 

附上例题一道:

0大学里的树木要维护 - 蓝桥云课 (lanqiao.cn)

AC代码:(注意此题直接用暴力做法只能过一半示例)

n,m = map(int, input().split())
a = [0] + list(map(int, input().split()))
dp = [0 for i in range(n+1)]
for i in range(n+1):
  dp[i] = dp[i - 1] + a[i] # 读入数据

for j in range(m):
  l,r = map(int, input().split())
  print(dp[r] - dp[l-1])

后记:

本来想说很多话,但是转念一想技术交流博客应该语言简洁,最后只想说,祝看到这里的大家与自己,30余天后的蓝桥杯,首战告捷,马到功成。对于我来说这是第一次,也是最后一次的蓝桥杯(因为是非科班),我只希望抓住最后的这次机会,努力学习,努力拼搏,不留遗憾。也愿看完此文的诸位努力学习,不留遗憾,这无关奖项的大小,高低;认识学习,学会学习,持续学习,才能在未来走的更远,愿诸位共勉,加油(ง •_•)ง

  • 39
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值