注意点:
计算机算法:枚举、排序、搜索、计数、贪心、动态规划、图论、数论、博奔论、概率论、计算几何、字符串算法等。
数据结构:数组、对象/结构、字符串、队列、栈、树、图、堆、平衡树/线段树、复杂数据结构、嵌套数据结构等。

门牌制作

【问题描述】
小蓝要为一条街的住户制作门牌号。这条街一共有 2020 位住户,门牌号从 1 到 2020 编号。小蓝制作门牌的方法是先制作 0 到 9 这几个数字字符,最后根据需要将字符粘贴到门牌上,例如门牌 1017 需要依次粘贴字符 1、0、1、7,即需要 1 个字符 0,2 个字符 1,1 个字符 7。
请问要制作所有的 1 到 2020 号门牌,总共需要多少个字符 2?

  1. k=0
  2. for i in range(1, 2021):
  3. for j in str(i):
  4. if j=='2':
  5. k+=1
  6. print(k) # 624

网友解法:

  1. ans = 0
  2. for i in range(1,2021):
  3. ans += str(i).count("2")
  4. print(ans)

跑步锻炼

【问题描述】
小蓝每天都锻炼身体。正常情况下,小蓝每天跑 1 千米。如果某天是周一或者月初(1 日),为了激励自己,小蓝要跑 2 千米。如果同时是周一或月初,小蓝也是跑 2 千米。小蓝跑步已经坚持了很长时间,从 2000 年 1 月 1 日周六(含)到 2020 年10 月 1 日周四(含)。请问这段时间小蓝总共跑步多少千米?
先算出总天数:
image.png
或者使用datetime库:

  1. import datetime
  2. sday = datetime.datetime.strptime('2000-1-1', '%Y-%m-%d')
  3. eday = datetime.datetime.strptime('2020-10-1', '%Y-%m-%d')
  4. print(eday-sday)
  5. # 7579 days, 0:00:00

不过,这里的7579只是天数差,而不是总天数。因为本题特别指明了起始日和终止日都是包含着的。而按上述两种算法都会少加一天,如图所示,实际上的总天数应该为天数差+1,如下图的总天数应该为3天:
image.png
所以,总天数实际上为7580天。
我的想法很简单,分别算出周一的天数A,月初的天数B,同时为周一和月初的天数C,则A+B-C即为跑2km的天数。
周一的天数A,直接用7579/7取整计算,即A为1082。
月初的天数B直接计算总月份即可表达。注意,2000年到2019年共有20年,240个月;2020年单独有10个月,所以共有250个月份,即250个月初日。
同时为周一和月初的天数C可以借助calendar库计算:

  1. import calendar
  2. count = 0
  3. # 先计算2000年-2019年,每年有12个月
  4. for year in range(2000, 2020):
  5. for month in range(1, 13):
  6. a = calendar.monthcalendar(year, month)
  7. if(a[0][0] == 1):
  8. count += 1
  9. # 再单独计算2020年,仅有10个月
  10. for month in range(1, 11):
  11. a = calendar.monthcalendar(2020, month)
  12. if(a[0][0] == 1):
  13. count += 1
  14. print(count)
  15. # 34

所以A+B-C为1298天。
那么7580+1298 = 8878天。

标准答案是8879,到底是哪里出了问题??

蛇形填数

【问题描述】
如下图所示,小明用从 1 开始的正整数“蛇形”填充无限大的矩阵。
1 2 6 7 15 …
3 5 8 14 …
4 9 13 …
10 12 …
11 …

容易看出矩阵第二行第二列中的数是 5。请你计算矩阵中第 20 行第 20 列的数是多少?

  1. import math
  2. def get_mid_value(k):
  3. result = 0
  4. for i in range(k):
  5. result += i
  6. result += math.ceil(k/2)
  7. print(result)
  8. get_mid_value(2*20-1) # 761

成绩统计

【问题描述】
小蓝给学生们组织了一场考试,卷面总分为 100 分,每个学生的得分都是一个 0 到 100 的整数。
如果得分至少是 60 分,则称为及格。如果得分至少为 85 分,则称为优秀。请计算及格率和优秀率,用百分数表示,百分号前的部分四舍五入保留整数。
【输入格式】
输入的第一行包含一个整数 n,表示考试人数。
接下来 n 行,每行包含一个 0 至 100 的整数,表示一个学生的得分。
【输出格式】
输出两行,每行一个百分数,分别表示及格率和优秀率。百分号前的部分
四舍五入保留整数。
【样例输入】
7
80
92
56
74
88
100
0
【样例输出】
71%
43%

  1. n = int(input())
  2. num = []
  3. for i in range(0, n):
  4. num.append(int(input()))
  5. nice = filter(lambda x:x>=85, num)
  6. good = filter(lambda x:x>=60, num)
  7. good_num = round(len(list(good))/n, 2)*100
  8. nice_num = round(len(list(nice))/n, 2)*100
  9. print(str(good_num).split('.')[0] + '%')
  10. print(str(nice_num).split('.')[0] + '%')

单词分析

【问题描述】
小蓝正在学习一门神奇的语言,这门语言中的单词都是由小写英文字母组成,有些单词很长,远远超过正常英文单词的长度。小蓝学了很长时间也记不住一些单词,他准备不再完全记忆这些单词,而是根据单词中哪个字母出现得最多来分辨单词。现在,请你帮助小蓝,给了一个单词后,帮助他找到出现最多的字母和这个字母出现的次数。
【输入格式】
输入一行包含一个单词,单词只由小写英文字母组成。
【输出格式】
输出两行,第一行包含一个英文字母,表示单词中出现得最多的字母是哪个。如果有多个字母出现的次数相等,输出字典序最小的那个。
第二行包含一个整数,表示出现得最多的那个字母在单词中出现的次数。
【样例输入】
lanqiao
【样例输出】
a
2
【样例输入】
longlonglongistoolong
【样例输出】
o
6

  1. characters = list(input())
  2. new_strs = [] # 记录唯一字符
  3. maxtime = 1 # 记录最多次数
  4. r = []
  5. # for i in characters:
  6. # if i not in new_strs:
  7. # new_strs.append(i)
  8. new_strs = list(set(characters)) # 使用set立刻去重
  9. for i in new_strs:
  10. c = characters.count(i)
  11. if c > maxtime:
  12. maxtime = c
  13. for i in new_strs:
  14. if characters.count(i) == maxtime:
  15. r.append(i)
  16. r.sort() # 按字典序排序
  17. print(r[0])
  18. print(maxtime)

小数第n位

原先错误的想法:

  1. x = input().split()
  2. a, b, n = [int(x[i]) for i in range(3)]
  3. t = str(a/b)
  4. point = t.find(".")
  5. x = t[point+n:point+n+3]
  6. if(len(x)==3):
  7. print(x)
  8. elif(len(x)==2):
  9. print(x+'0')
  10. elif(len(x)==1):
  11. print(x+'00')
  12. elif(len(x)==0):
  13. print('000')

未考虑到 n 过大时的情况,正确的题解为:

  1. def quickPow(a, n): # 快速幂
  2. res = 1
  3. while(n):
  4. if n%2 != 0:
  5. res *= a
  6. a *= a # 翻倍
  7. n >>= 1 # 二进制右移一位
  8. return res
  9. a, b, n = map(int, input().split())
  10. mod = b * 1000
  11. print(a * quick(10, n + 2) % (mod) // b)

蓝桥杯真题 - 图3

成绩分析

重点是计算平均分的四舍五入。使用Decimal

  1. from decimal import Decimal
  2. n = int(input())
  3. x = []
  4. for i in range(n):
  5. x.append(int(input()))
  6. print(max(x))
  7. print(min(x))
  8. avg = Decimal(sum(x)/n).quantize(Decimal("0.01"), rounding="ROUND_HALF_UP")
  9. print(avg)