注意:加了题目链接

目录

  • 注意:加了题目链接
  • 一、打表模拟法
    • 介绍
    • 1. 算式问题
      • 题目描述
      • 解析与代码演示
    • 2. 求值
      • 题目描述
      • 解析与代码演示
    • 3. 既约分数
      • 题目描述
      • 解析与代码演示
    • 4. 天干地支
      • 题目描述
      • 输入描述
      • 输出描述
      • 输入输出样例
        • 示例
      • 解析与代码演示
  • 二、递推递归法
    • 介绍
    • 1. 斐波那契数列
      • 题目描述
      • 输入描述
      • 输出描述
      • 输入输出样例
        • 示例
      • 解析与代码演示
    • 2. 斐波那契数列多次查询版
      • 题目描述
      • 输入描述
      • 输出描述
      • 输入输出样例
        • 示例
      • 解析与代码演示
    • 3. 数字三角形
      • 题目描述
      • 输入描述
      • 输出描述
      • 输入输出样例
        • 示例
      • 解析与代码演示
  • 三、枚举法
    • 介绍
    • 1. 42 点问题
      • 题目描述
      • 输入描述
      • 输出描述
      • 输入输出样例
        • 示例
      • 样例说明
      • 解析与代码演示
    • 2. 公平抽签
      • 题目描述
      • 输入描述
      • 输出描述
      • 输入输出样例
        • 示例
      • 解析与代码演示
    • 3. 座次问题
      • 题目描述
      • 输入描述
      • 输出描述
      • 输入输出样例
        • 示例
      • 解析与代码演示
  • 四、贪心算法
    • 介绍
    • 1. 找零问题
      • 题目描述
      • 输入描述
      • 输出描述
        • 示例
      • 解析与代码演示
    • 2. 贪心的自助餐
      • 题目描述
      • 输入描述
      • 输出描述
        • 示例
      • 解析与代码演示
  • 五、差分与前缀和
    • 5.1 差分法
      • 介绍
      • 1. 大学里的树木要打药
        • 题目描述
        • 输入描述
        • 输出描述
          • 示例
        • 解析与代码演示
    • 5.2 前缀和
      • 介绍
      • 1. 大学里的树木要维护
        • 题目描述
        • 输入描述
        • 输出描述
        • 输入输出描述
          • 示例
        • 解析与代码演示

一、打表模拟法

介绍

模拟法是比赛中最常用的方法,使用各种算法大都离不开模拟,而对于一些只是需要结果的题目来说打表法是一个非常好的解决方案,而且对于数论等其他需要找规律的题目来说,打表法是一个非常有用的方法。这种方法一般多数出现在填空题中。

下面给出几道关于打表模拟法的蓝桥杯真题。

1. 算式问题

链接:算式问题

题目描述

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

看这个算式:
☆☆☆ + ☆☆☆ = ☆☆☆
如果每个五角星代表 111 ~ 999 的不同的数字。
这个算式有多少种可能的正确填写方法?

173 + 286 = 459
295 + 173 = 468
173 + 295 = 468
183 + 492 = 675

以上都是正确的填写法!
注意: 111+222=333111 + 222 = 333111+222=333 是错误的填写法! 因为每个数字必须是不同的! 也就是说:111 ~ 999中的所有数字,每个必须出现且仅出现一次!

注意:不包括数字 “0”“0”“0”!

注意: 满足加法交换率的式子算两种不同的答案。 所以答案肯定是个偶数!

解析与代码演示

对于这道题,一眼我们就知道可以用暴力枚举的方法来解决,因为这是一道填空题,所以我们可以不管时间的长短,写完直接让程序跑起来就行。

根据题目要求,最小的三位数是123,最大的三位数是987,所以我们可以从123枚举到987。

count = 0
for a in range(123, 988):for b in range(123, 988-a):c = a + bif c < 1000:s = str(a) + str(b) + str(c)if '0' not in s:if len(set(s)) == 9:count += 1print(count)

答案:336

2. 求值

链接:求值

题目描述

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

学习了约数后,小明对于约数很好奇,他发现,给定一个正整数 ttt,总是可以找到含有 ttt 个约数的整数。小明对于含有 ttt 个约数的最小数非常感兴趣,并把它定义为 StS_tSt​。

例如 S1=1,S2=2,S3=4,S4=6,⋅⋅⋅S_1 = 1, S_2 = 2, S_3 = 4, S_4 = 6,· · ·S1​=1,S2​=2,S3​=4,S4​=6,⋅⋅⋅。
现在小明想知道,当 t=100t = 100t=100 时,StS_tSt​是多少?即 S100S_{100}S100​是多少?

解析与代码演示

这道题是要求找出含有100个约数的数字,我们第一步可以先写一个一个数字含有的约数总和,第二步就可以直接暴力枚举了。

def cnt(a):ans=0for j in range(1,a+1):if a%j ==0:ans+=1return   ans
for i in range(1,400000):if cnt(i)==100:print(cnt(i),' ',i)break

答案:45360

3. 既约分数

链接:既约分数

题目描述

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

如果一个分数的分子和分母的最大公约数是 111,这个分数称为既约分数。

例如 34,18,71\frac{3}{4} ,\frac{1}{8} ,\frac{7}{1}43​,81​,17​ , 都是既约分数。
请问,有多少个既约分数,分子和分母都是 111 到 202020202020 之间的整数(包括 111 和 202020202020)?

解析与代码演示

def gcd2(a, b):while b > 0:r = a % ba = bb = rreturn a
count = 0
for i in range(1, 2021):for j in range(1, 2021):if gcd2(i, j) == 1:count += 1
print(count)

答案:2481215

4. 天干地支

链接:天干地支

题目描述

古代中国使用天干地支来记录当前的年份。

天干一共有十个,分别为:甲(jiǎ)、乙(yǐ)、丙(bǐng)、丁(dīng)、戊(wù)、己(jǐ)、庚(gēng)、辛(xīn)、壬(rén)、癸(guǐ)。

地支一共有十二个,分别为:子(zǐ)、丑(chǒu)、寅(yín)、卯(mǎo)、辰(chén)、巳(sì)、午(wǔ)、未(wèi)、申(shēn)、酉(yǒu)、戌(xū)、 亥(hài)。

将天干和地支连起来,就组成了一个天干地支的年份,例如:甲子。

202020202020 年是庚子年。

每过一年,天干和地支都会移动到下一个。例如 202120212021 年是辛丑年。

每过 606060 年,天干会循环 666 轮,地支会循环 555 轮,所以天干地支纪年每 606060 年轮回一次。例如 190019001900 年,196019601960 年,202020202020 年都是庚子年。

给定一个公元纪年的年份,请输出这一年的天干地支年份。

输入描述

输入一行包含一个正整数,表示公元年份。

其中有 ,输入的公元年份为不超过 999999999999 的正整数。

输出描述

输入一行包含一个正整数,表示公元年份。

输入输出样例

示例

输入

2020

输出

2020

解析与代码演示

我们可以先判断 0000 年的天干 和地支。天干是10年一个轮回,又已知2020年是庚子年,所以2020 % 10 = 0,0000 年的天干就是庚,2020 % 12 = 4,往前推四年,地支是申。由此我们可以通过模拟法来推到。

  • N-1%10=0 时 天干为庚
  • N-1%10=1 时 天干为辛
  • N-1%12=0 时 地支为申
  • N-1%12=1 时 地支为酉
tg = ["geng", "xin", "ren", "gui", "jia", "yi", "bing", "ding", "wu", "ji"]
dz = ["shen", "you", "xu", "hai", "zi", "chou","yin", "mou", "chen", "si", "wu", "wei"]year = int(input())
print(tg[year % 10], dz[year % 12], sep='')

二、递推递归法

介绍

递推算法的思想

  • 首要问题是先找到各个相邻数据项之间的递推关系;
  • 递推关系避开了求通项公式的麻烦,且有些题目的通项公式很难求,或者不能进行求解;
  • 将复杂问题分解为若干步骤的简单运算;
  • 一般来说递推算法就是一种特殊的迭代算法。
    递归算法设计的一般步骤
  1. 根据题目设计递归函数中的运算部分;
  2. 根据题目找到递归公式,题目可能会隐含给出,也可能需要自己进行推导;
  3. 找到递归出口,即递归的终止条件。

下面给出几道关于递推递归法的蓝桥杯真题。

1. 斐波那契数列

链接:斐波那契数列

题目描述

斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,其指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、⋯0、1、1、2、3、5、8、13、21、34、\cdots0、1、1、2、3、5、8、13、21、34、⋯

在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1,F(n)=F(n−1)+F(n−2)(n≥2,n∈N∗)F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n \in N^*)F(0)=0,F(1)=1,F(n)=F(n−1)+F(n−2)(n≥2,n∈N∗)

现给定一个正整数 nnn,请求出该数列中第 nnn 项的值是多少。

输入描述

输入仅 111 行,包含一个整数 NNN。0≤N≤250\leq N \leq 250≤N≤25。

输出描述

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

输入输出样例

示例

输入

3

输出

2

解析与代码演示

对于题目而言,已经给出了递推公式:
F(n) = F(n-1) + F(n-2),也就是F(n) + F(n+1) = F(n+2)
所以这道题既可以用递归也可以用递推。
对于递归:
如:
F(6) = F(5) + F(4) = F(4) + F(3) + F(3) + F(2) = …
到最后肯定都是F(0)和F(1),所以需要设置终止条件

def f(x):if x == 0:  # 终止条件return 0if x == 1:  # 终止条件return 1return f(x-1)+f(x-2)
n = int(input())
print(f(n))

对于递推:
我们需要设置好递推的起点,也就是F(0)和F(1),之后让递推公式一直循环下去。

n = int(input())f_0 = 0 # F(n)
f_1 = 1 # F(n+1)
f_n = 0 # F(n+2)暂时为空
if n == 0:f_n = 0
elif n == 1:f_n = 1
else:for i in range(n-1):f_n = f_0 + f_1 # F(n+2) = F(n) + F(n+1)# 更新下轮的数值f_0 = f_1 # F(n) = F(n+1)f_1 = f_n # F(n+1) = F(n+2)print(f_n)

2. 斐波那契数列多次查询版

链接:斐波那契数列多次查询版

题目描述

斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,其指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、⋯0、1、1、2、3、5、8、13、21、34、\cdots0、1、1、2、3、5、8、13、21、34、⋯

在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1,F(n)=F(n−1)+F(n−2)(n≥2,n∈N∗)F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n \in N^*)F(0)=0,F(1)=1,F(n)=F(n−1)+F(n−2)(n≥2,n∈N∗)

现给定一个正整数 MMM,表示 MMM 个查询。每个查询给定一个正整数 NNN,请求出该数列中第 NNN 项的值是多少。

输入描述

第 111 行为一个整数 TTT,表示测试数据数量。

接下来的 TTT 行每行包含一个正整数 NNN。

1≤T≤5×102,1≤N≤30。1 \leq T \leq 5\times 10^2 ,1\leq N \leq 30。1≤T≤5×102,1≤N≤30。

输出描述

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

输入输出样例

示例

输入

2
3
4

输出

2
3

解析与代码演示

这道题无疑是再上一题的基础加上一个查询操作,由于N在1~30范围内,我们可以把斐波那契数列的前三十项存在列表中,方便查询。

注意:在蓝桥杯测评时,只会用你的输出来比较,所以我们只关心答案即可!不用害怕输入输出写在一起。

n = int(input())def func(n):f_0 = 0 # F(n)f_1 = 1 # F(n+1)f_n = 0 # F(n+2)暂时为空if n == 0:f_n = 0elif n == 1:f_n = 1else:for i in range(n-1):f_n = f_0 + f_1 # F(n+2) = F(n) + F(n+1)# 更新下轮的数值f_0 = f_1 # F(n) = F(n+1)f_1 = f_n # F(n+1) = F(n+2)return f_n
a = []
for i in range(0, 30):a.append(func(i))for j in range(n):x = int(input())print(a[x])

3. 数字三角形

链接:数字三角形

题目描述


上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和(路径上的每一步只可沿左斜线向下或右斜线向下走)。

输入描述

输入的第一行包含一个整数 N(1≤N≤100)N\ (1 \leq N \leq 100)N (1≤N≤100),表示三角形的行数。

下面的 NNN 行给出数字三角形。数字三角形上的数都是 000 至 999999 之间的整数。

输出描述

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

输入输出样例

示例

输入

5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

输出

30

解析与代码演示

这道题的解法可以用动态规划、暴力枚举。从递推的方法看。当我们在第i层,第j列时,在选择下一条路径时肯定时选择最大的那一条,即a[i][j]=max{a[i][j]+a[i+1][j],a[i][j]+a[i+1][j+1]}a[i][j]=max\lbrace a[i][j]+a[i + 1][j],a[i][j]+a[i + 1][j+1] \rbracea[i][j]=max{a[i][j]+a[i+1][j],a[i][j]+a[i+1][j+1]},显而易见,从第一行开始是不可行的,所以我们要采用逆推的方法,从最后一层开始向上推。

a = [[0] * 101] * 101n = int(input())# 输入数字三角形的值
for i in range(1, n+1):a[i] = input().split()a[i] = list(map(int, a[i]))for i in range(n - 1, 0, -1):# 最后一层逆推for j in range(0, i):# 路径选择if a[i + 1][j] >= a[i + 1][j + 1]:a[i][j] += a[i + 1][j]else:a[i][j] += a[i + 1][j + 1]print(a[1][0])

三、枚举法

介绍

枚举的基本思想
将问题的所有可能成为答案的解一一列举,然后根据问题所给出的条件判断此解是否合适,如果合适就保留,反之则舍弃。需要注意的是枚举最重要的时把所有情况都列举出来,缺一不可。

下面给出几道关于打表模拟法的蓝桥杯真题。

1. 42 点问题

链接:42 点问题

题目描述

众所周知在扑克牌中,有一个老掉牙的游戏叫做 242424 点:选取 444 张牌进行加减乘除,看是否能得出 242424 这个答案。

现在小蓝同学发明了一个新游戏,他从扑克牌中依次抽出 666 张牌(注意不是一次抽出),进行计算,看是否能够组成 424242 点 , 满足输出 YES,反之输出 NO

请你设计一个程序对该问题进行解答。

输入描述

输出仅一行包含 666 个字符。
保证字符 ∈ 3 4 5 6 7 8 9 10 J Q K A 2

输出描述

若给出到字符能够组成 424242 点 , 满足输出 YES,反之输出 NO

输入输出样例

示例

输入

K A Q 6 2 3

输出

YES

样例说明

  • KA=K即131=13KA=K即131=13KA=K即131=13
  • 13/12=1 保留整数
  • 1+6=7
  • 7∗2=14
  • 14∗3=42

解析与代码演示

对于这道题,我们可以进行暴力枚举,因为是6个数依此运算,我们就可以创建5个列表来依此存储它们5次运算的结果,就是前一个数和后一个数的加减乘除的运算结果。

a = list(map(str, input().split()))
for i in range(len(a)):if a[i] == 'A':a[i] = 1elif a[i] == 'J':a[i] = 11elif a[i] == 'Q':a[i] = 12elif a[i] == 'K':a[i] = 13else:a[i] = ord(a[i]) - ord('0')
l1 = [[],[],[],[],[]]
l1[0].append(a[0]+a[1])
l1[0].append(a[0]-a[1])
l1[0].append(a[0]*a[1])
l1[0].append(int(a[0]/a[1]))
for i in range(1, 5):for j in range(len(l1[i-1])):# 运算前一个列表内所有的数字与后一个数字的加减乘除l1[i].append(l1[i-1][j] + a[i+1])l1[i].append(l1[i-1][j] - a[i+1])l1[i].append(l1[i-1][j] * a[i+1])l1[i].append(int(l1[i-1][j] / a[i+1]))flag = 0
for i in range(len(l1[-1])):if l1[-1][i] == 42:flag = 1breakelse:continue
if flag == 1:print("YES")
else:print("NO")

2. 公平抽签

链接:公平抽签

题目描述

小AAA的学校,蓝桥杯的参赛名额非常有限,只有 mmm 个名额,但是共有 nnn 个人报名。

作为老师非常苦恼,他不知道该让谁去,他在寻求一个绝对公平的方式。

于是他准备让大家抽签决定,即 mmm 个签是去,剩下的是不去。

小AAA非常想弄明白最后的抽签结果会有多少种不同到情况,请你设计一个程序帮帮小AAA!

输入描述

输入第一行包含两个字符 n,mn,mn,m,其含义如题所述。

接下来第二行到第 n+1n+1n+1 行每行包含一个字符串 SSS ,表示个人名。

1≤m≤n≤151≤m≤n≤151≤m≤n≤15。

输出描述

输出共若干行,每行包含 mmm 个字符串,表示该结果被选中到人名。

输入输出样例

示例

输入

3 2
xiaowang
xiaoA
xiaoli

输出

xiaowang xiaoA
xiaowang xiaoli
xiaoA xiaoli

解析与代码演示

对于这道题,我们可以使用排列组合的方式进行求解,由于python自带求排列组合的库,我们就可以不用自己写啦。


import itertools
n, m = map(int, input().split())
l1 = []
l2 = []
for i in range(n):name = input()l1.append(name)
for i in range(1,len(l1)+1):iter = itertools.combinations(l1,i)l2.append(list(iter))
l3 = l2[m-1]
for name in l3:print(' '.join(list(name)))
# print(l2)

3. 座次问题

链接:座次问题

题目描述

小 AAA 的学校,老师好不容易解决了蓝桥杯的报名问题,现在老师又犯愁了。

现在有 NNN 位同学参加比赛,但是老师想给他们排座位,但是排列方式太多了。

老师非常想弄明白最后的排座次的结果是什么样子的,到底有多少种结果。

请设计一个程序帮助老师。

最后输出各种情况的人名即可,一行一种情况,每种情况的名字按照报名即输入顺序排序。

输入描述

输入第一行包含一个整数 NNN。
接下来 NNN 行每行包含一个字符串 SiS_iSi​,表示人名。
1≤N≤10,∑i=1N∣Si∣≤102。1≤N≤10,\sum\limits_{i=1}^{N} |S_i| \leq 10^2 。1≤N≤10,i=1∑N​∣Si​∣≤102。

输出描述

输出共若干行,每行输出各种情况的人名。一行一种情况,每种情况的名字按照报名即输入顺序排序。

输入输出样例

示例

输入

3
xiaowang
xiaoA
xiaoli

输出

xiaowang xiaoA xiaoli
xiaowang xiaoli xiaoA
xiaoA xiaowang xiaoli
xiaoA xiaoli xiaowang
xiaoli xiaowang xiaoA
xiaoli xiaoA xiaowang

解析与代码演示

这题也是非常的简单,一眼看出就是全排列,我们可以直接使用python自带的全排列的库。

from itertools import permutations
n = int(input())
l1 = []
for i in range(n):name = input()l1.append(name)
l2 = list(permutations(l1))
for names in l2:print(' '.join(list(names)))

四、贪心算法

介绍

贪心算法,又称贪婪算法。是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而使得问题得到全局最优解。

贪心算法主要适用于最优化问题,如:MST 问题。有时候贪心算法并不能得到最优答案,但是能得到精确答案的近似答案。有时可以辅助其他算法得到不是那么精确的结果。

适用范围
所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。
贪心算法的解题思路

  1. 证明原问题的最优解之一可以由贪心选择得到。
  2. 将最优化问题转化为这样一个问题,即先做出选择,再解决剩下的一个子问题。
  3. 对每一子问题一一求解,得到子问题的局部最优解;
  4. 把子问题的解局部最优解合成原来解问题的一个解

下面给出几道关于打表模拟法的蓝桥杯真题。

1. 找零问题

链接:找零问题

题目描述

蓝桥商店的老板需要找零 nnn 元钱。
钱币的面额有:100100100 元、505050 元、202020 元、555 元、111 元,问如何找零使得所需钱币的数量最少?

注意:nnn 可能为 000,也能为几百元(别问,问就是来着里微信提现来了)

输入描述

在第一行给出测试例个数 NNN,代表需要找零的钱数。
1≤N≤1051≤N≤10^51≤N≤105。

输出描述

输出共有 555 行,每一行输出数据输出找零的金额与数量,详情看样例。

示例

输入

365

输出

100:3
50:1
20:0
5:3
1:0

解析与代码演示

对于这道题,我们需要找零使得所需钱币的数量最少,那我肯定就要从金额大的面额开始找,如365,我们就需要先找3个100,剩下65又可以找一个50,剩下15,20的面额不够,就可以用3个5元的面额。

a = [100, 50, 20, 5, 1]
n = int(input())
for i in range(len(a)):print(str(a[i])+':'+str(n//a[i]))n = n%a[i]

2. 贪心的自助餐

链接:贪心的自助餐

题目描述

小BBB同学想去吃自助餐,但是他是那种比较节俭的的人,既不想浪费食物,又想尽可能吃的贵一点,他于是私下里做了调查。

小蓝餐厅的自助餐有 nnn 种食材,每种食材都有它的价格。

而且也能估计出每一份的重量,所以他列了一个表格:

菜品 价格(元) 重量(g)
红烧牛肉 30 300
油闷大虾 8 5
四喜丸子 4 8
三文鱼 5 3
排骨 18 200
麻辣兔头 20 120
高汤海参 40 70
扇贝粉丝 8 32
牛排 79 240

小BBB的饭量为 C(g)C(g)C(g),他想知道在不超过饭量的情况下他最多能吃多少钱的菜品。

请你设计一个程序帮助小BBB计算他的最多吃了多少钱。(假设自助餐厅的菜品供应同样的菜品每个人只能取一份。)

输入描述

第一行输入两个整数 n,Cn,C(0≤n≤103,0≤C≤104)n,Cn,C(0\leq n\leq 10^3,0\leq C\leq 10^4)n,Cn,C(0≤n≤103,0≤C≤104),其中 nnn 为菜品数量,CCC 为小BBB的肚子容量。

接下来 nnn 行每行输入两个数 v[i],w[i],v[i]v[i],w[i],v[i]v[i],w[i],v[i] 是第 iii 个菜品的价值,w[i]w[i]w[i] 表示第 iii 个菜品的重量(0≤v[i],w[i]≤104)(0\leq v[i],w[i] \leq 10^4)(0≤v[i],w[i]≤104)。

输出描述

输出一行数据,表示最大的价值,保留小数点后三位数。

示例

输入

20 1000
1 22
2 43
123 214
12 2
123 432
21 223
22 16
77 49
34 78
34 9
43 677
21 34
23 23
12 56
332 56
21 99
123 545
389 33
12 999
23 88

输出

1204.114

解析与代码演示

对于这道题总是要挑贵的吃,但一方面人会饱,所以我们需要按照每个事物的单价来挑选事物,尽量选贵的。

# 菜的数量、能吃的重量
n, c = map(int, input().split())
l1 = []
for i in range(n):# 价格 重量v, w = map(int, input().split())l1.append((v, w))
# 按单价价格最高来排序
l1 = sorted(l1, key=lambda x:x[0]/x[1], reverse=True)
i = 0
money = 0
while i < len(l1):if l1[i][1] >= c:money = money + (l1[i][0] / l1[i][1]) * cbreakelse:money += l1[i][0]c -= l1[i][1]i += 1
print('%.3f'%(money))

五、差分与前缀和

5.1 差分法

介绍

差分法的应用主要是用于处理区间问题。当某一个数组要在很多不确定的区间,加上相同的一个数。我们如果每个都进行加法操作的话,那么复杂度是 O(nm) ,非常消耗时间。如果采用差分法,我们可以将O(nm)降低到O(n)。

解题步骤

  1. b[0] = a[0]
  2. 从第 2 项到 n 项,利用 b[i]=a[i]-a[i-1] 差分式(从第一项开始);
  3. 对于区间端点操作加减;
  4. 差分还原(前缀和)。

例子:
对a = [1,2,3,4,5,7,2]中从第二个到第五个元素都加3。

a = [1,2,3,4,5,7,2]
b = [0 for i in range(len(a))]
# 第一步:b[0] = a[0]
b[0] = a[0]
# 第二步:差分
for i in range(1, len(a)):b[i] = a[i] - a[i-1]
# 第三步:对区间t1, t2+1进行加减
b[1] += 3
b[5] -= 3
# 第四步: 差分还原(前缀和)
for i in range(1, len(a)):b[i] += b[i-1]
print(b)

下面给出关于打表模拟法的蓝桥杯真题。

1. 大学里的树木要打药

链接:大学里的树木要打药

题目描述

教室外有 NNN 棵树(树的编号从 0∼N−10\sim N-10∼N−1),根据不同的位置和树种,学校要对其上不同的药。

因为树的排列成线性,且非常长,我们可以将它们看作一条直线给他们编号。

对于树的药是成区间分布,比如 3∼53 \sim 53∼5号的树靠近下水道,所以他们要用驱蚊虫的药, 20∼2620 \sim 2620∼26号的树,他们排水不好,容易涝所以要给他们用点促进根系的药 ⋯\cdots⋯诸如此类。

每种不同的药要花不同的钱。

现在已知共有 MMM 个这样的区间,并且给你每个区间花的钱,问最后这些树木要花多少药费。

输入描述

每组输入的第一行有两个整数 NNN和 MMM。NNN 代表马路的共计多少棵树,MMM 代表区间的数目,NNN 和 MMM 之间用一个空格隔开。

接下来的 MMM 行每行包含三个不同的整数,用一个空格隔开,分别表示一个区域的起始点 LLL 和终止点 RRR 的坐标,以及花费。

1≤L≤R≤N≤106,1≤M≤1051\leq L\leq R \leq N \leq 10^6,1\leq M\leq 10^51≤L≤R≤N≤106,1≤M≤105,保证花费总和不超过 int 范围。

输出描述

示例

输入

500 3
150 300 4
100 200 20
470 471 19

输出

2662

解析与代码演示

对于这道题,我们可以使用一个全为0的a数组,长度为n,初始化,所有的价格为0,用差分法给每个区件做加法,最后求出数组之和。

n, m = map(int, input().split())
a = [0 for i in range(n)]
s = [0 for i in range(len(a))]
for i in range(1, len(a)):s[i] = a[i] - a[i-1]
s[0] = a[0]
for i in range(m):t1, t2, v = map(int, input().split())s[t1-1] += vs[t2] -= v
for i in range(1, len(a)):s[i] += s[i-1]
print(sum(s))

5.2 前缀和

介绍

前缀和是指某序列的前 n 项和,当对于某一数组区间进行多次询问,[L,r] 的和时,如果正常处理,那么我们每次都要 [l,r]。查询 N 次,那么时间复杂度也是 O(nm) 。
解题步骤

  1. 利用b[i] = a[i-1] + b[i-1]求出前缀和
  2. 初始化时b[0] = 0
  3. 利用端点相减求区间和b[n] - b[m-1]

例子:求a = [1,2,3,4,5,7,2]第二个到第五个元素的和

a = [1,2,3,4,5,7,2]
b = [0 for i in range(len(a)+1)]
# 第一步:利用b[i] = a[i-1] + b[i-1]求出前缀和
for i in range(1, len(a)+1):b[i] = b[i-1] + a[i-1]
print(b)
# 第三步
print(b[5]-b[2-1])

下面给出关于打表模拟法的蓝桥杯真题。

1. 大学里的树木要维护

链接:大学里的树木要维护

题目描述

教室外有 NNN 棵树(树的编号从 1∼N1\sim N1∼N),根据不同的位置和树种,学校已经对其进行了多年的维护。

因为树的排列成线性,且非常长,我们可以将它们看作一条直线给他们编号。

由于已经维护了多年,每一个树都由学校的园艺人员进行了维护费用的统计。

每棵树的前期维护费用各不相同,但是由于未来需要要打药,所以有些树木的维护费用太高的话,就要重新种植。

由于维护费用也称区间分布,所以常常需要统一个区间里的树木的维护开销。

现给定一个长度为 NNN 的数组 AAA 以及 MMM 个查询,AiA_iAi​
​表示第 iii 棵树到维护费用。对于每个查询包含一个区间,园艺人员想知道该区间内的树木维护的开销是多少。

请你编写程序帮帮他!

输入描述

每组输入的第一行有两个整数 NNN和 MMM。NNN 代表马路的共计多少棵树,MMM 代表区间的数目,NNN 和 MMM 之间用一个空格隔开。

接下来的一行,包含 NNN 个数 A1,A2,⋯,ANA_1,A_2,\cdots,A_NA1​,A2​,⋯,AN​
​,分别表示每棵树的维护费用,每个数之间用空格隔开。

接下来的 MMM 行每行包含两个不同的整数,用一个空格隔开,表示一个区域的起始点 LLL 和终止点 RRR 的坐标。

输出描述

输出包括 MMM 行,每一行只包含一个整数,表示维护的开销。

输入输出描述

示例

输入

10 3
7 5 6 4 2 5 0 8 5 3
1 5
2 6
3 7

输出

24
22
17

解析与代码演示

n, m = map(int, input().split())
a = list(map(int, input().split()))
b = [0 for i in range(len(a)+1)]
for i in range(1, len(a)+1):b[i] = b[i-1] + a[i-1]
for i in range(m):t1, t2 = map(int, input().split())print(b[t2] - b[t1-1])

蓝桥杯python省赛冲刺篇2——常用算法的详细解析及对应蓝桥杯真题:打表模拟法、递推递归法、枚举法、贪心算法、差分与前缀和相关推荐

  1. 蓝桥杯python省赛冲刺篇1——数据结构基础:队列、栈、排序

    注意:加了题目链接 目录 注意:加了题目链接 CLZ 的银行普通队列(队列) 题目描述 输入描述 输出描述 输入输出样例 示例1 代码演示 小邋遢的衣橱(栈) 题目描述 输入描述 输出描述 输入输出样 ...

  2. c# 扩展方法奇思妙用变态篇一:由 Fibonacci 数列引出 “委托扩展” 及 “递推递归委托”...

    先回顾一个数列的概念:按一定次序排列的一列 数 称为数列...(请参见百度百科:数列) 几个简单的数列:       1, 1, 1, 1, 1, 1, 1...                //数 ...

  3. python认证考试有哪些_Python入门习题(19)——CCF CSP认证考试真题:中间数

    问题描述 试题编号:201703-1 试题名称:分蛋糕 时间限制:1.0s 内存限制:256.0MB 问题描述 小明今天生日,他有n块蛋糕要分给朋友们吃,这n块蛋糕(编号为1到n)的重量分别为a1, ...

  4. python中英文字频率_python 统计英语文档词汇出现频率,以六级真题为例

    很多人免不了参加各种英语考试,词汇量就是参加英语考试的一个拦路虎,单词不认识,技巧再多也枉然.但考试大纲要求的单词太多了,时间紧,任务重,背了又容易忘,如果能知道真题中词汇出现的频率高低,那么有意识的 ...

  5. 【蓝桥杯国赛真题02】python输出自然数 青少年组蓝桥杯python 国赛比赛真题解析

    目录 python输出自然数 一.题目要求 1.编程实现 2.输入输出 3.评分标准

  6. 未名湖边的烦恼-蓝桥杯算法训练题-递推/递归

    问题描述 每年冬天,北大未名湖上都是滑冰的好地方.北大体育组准备了许多冰鞋,可是人太多了,每天下午收工后,常常一双冰鞋都不剩. 每天早上,租鞋窗口都会排起长龙,假设有还鞋的m个,有需要租鞋的n个.现在 ...

  7. 蓝桥杯 DFS经典题 —— 算式900、寒假作业(告别枚举法)

    类似于 算式 900.寒假作业这种题目,可以直接暴力破解,但是它非常的浪费时间,而且程序不是太过于美观,很容易让我们对算法失去兴趣,今天,我们告别传统的暴力破解,使用伟大搜索算法 -- DFS(深度优 ...

  8. java春招面试冲刺系列:redis基础知识详细解析

    目录 学习计划 学习笔记 百问 redis在什么情况下会变慢? 单线程的redis,如何知道要运行定时任务? 学习计划 Redis的介绍.优缺点.使用场景 Linux中的安装 常用命令 Redis各个 ...

  9. python装饰器参数讲解_python装饰器的详细解析

    写在前面: python装饰器(fuctional decorators)就是用于拓展原来函数功能的一种函数,目的是在不改变原函数名(或类名)的情况下,给函数增加新的功能. 这个函数的特殊之处在于它的 ...

最新文章

  1. 转载自搜狐科技【技术那些事儿】LTE网络中的用户数据库HSS与传统2G/3G的HLR有何区别?能否融合组网?...
  2. Build path contains duplicate entry
  3. python3.5文档
  4. LeetCode 281. 锯齿迭代器(map+vector)
  5. dev调试时无法进入下一步_Linux开源实时EtherCAT主站操作系统安装和调试笔记
  6. Java通过 p12 建立ssl链接
  7. 嵌入式基础面八股文——死锁与饥饿(4)
  8. 太强了!这款轻量级中间件几行代码就搞定SpringBoot的分库分表问题
  9. 下载编译goldfish内核
  10. 【C语言程序设计】C语言求圆周率π(三种方法)
  11. 读书笔记-人月神话13
  12. ACM 退役 碎碎念
  13. wifi一到晚上服务器无响应,一到晚上九点,网络就开始卡了?主要原因是这三点!...
  14. 人工智能在解放客服,还是在解散客服?
  15. 项目经理的文档提升能力
  16. 微信小程序中使用腾讯地图,导航到目的地
  17. 计算机主机装配视频,预算一万如何组装电脑?新媒体视频剪辑等影视专业装机指南2020.8...
  18. 这波啊,是王心凌技术男孩
  19. 卡西欧将发布紧凑型G-SHOCK新品,为锻炼和日常使用提供便利
  20. mdf是什么mysql_mdf是数据库文件吗

热门文章

  1. Uni-app学习过程(1)
  2. java实现excel导入导出(jxl),Java面试题及解析
  3. 学习中如何建立自己的资源库?
  4. Python对于私有化的处理
  5. 如何在Java面试中克服恐惧?
  6. electron中showMessageBox里关于选择按钮回调函数不执行的错误
  7. 开关二极管和肖特基二极管比较
  8. 嵌入式Linux根文件系统制作
  9. 解决Max retries exceeded with url的问题
  10. 云、AI、5G技术驱动时代,文娱产业如何实现云上突围?