蓝桥杯刷题算法实战解析

门牌制作

代码如下:

python 复制代码
num = 0
for i in range(1, 2021):
  num += str(i).count('2')
print(num)

特别数的和

代码如下:

python 复制代码
n = int(input())

ans = 0
for i in range(1, n + 1):
    if '2' in str(i) or '0' in str(i) or '1' in str(i) or '9' in str(i):
        ans += i
print(ans)

成绩统计

代码如下:

python 复制代码
n = int(input())
num = []
for _ in range(n):
    num.append(int(input()))

ok, well = 0, 0
for x in num:
    if x >= 85:
        well += 1
    if x >= 60:
        ok += 1
ans1 = (ok / n) * 100
ans2 = (well / n) * 100
print("{:.0f}%".format(ans1))
print("{:.0f}%".format(ans2))

冰雹数

代码如下:

python 复制代码
n = int(input())
max_value = 0  # 记录所有数字变换过程中的最大值

# 遍历从1到n的所有数字
for i in range(1, n + 1):
    num = i
    # 更新当前数字本身(它也是序列的一部分)
    if num > max_value:
        max_value = num
    # 进行冰雹变换
    while num != 1:
        if num % 2 == 0:
            num //= 2
        else:
            num = num * 3 + 1
        # 更新最大值
        if num > max_value:
            max_value = num
print(max_value)

饮料换购

代码如下:

python 复制代码
n = int(input())
ans = n
while n >= 3:
    ans += n // 3
    n = n % 3 + n // 3
print(ans)

三角回文数

代码如下:

python 复制代码
def is_palindrome(n):
    s = str(n)
    return s == s[::-1]

def is_triangular(n):
    # 解 k^2 + k - 2n = 0
    # 判别式 D = 1 + 8n
    D = 1 + 8 * n
    root = int(D ** 0.5)
    return root * root == D and (root - 1) % 2 == 0

n = 20220514
while True:
    if is_triangular(n) and is_palindrome(n):
        print(n)
        break
    n += 1

递增三元组

二分查找:bisect库

ls = 所查找的数组,x = 需要查找的值

index1 = bisect.bisect(ls, x) index2 = bisect.bisect_left(ls, x) index3 = bisect.bisec_right(ls, x)

注意:bisect.biscet(ls, x) == bisect.bisect_right(ls, x)

1.所查找的数组中无元素 x,返回 x 在 ls 中的"插入点索引,且保持数组有序"。

python 复制代码
import bisect

ls = [1,5,9,13,17]
index1 = bisect.bisect(ls,7)
index2 = bisect.bisect_left(ls,7)
index3 = bisect.bisect_right(ls,7)
print("index1 = {}, index2 = {}, index3 = {}".format(index1, index2, index3))
# index1 = 2, index2 = 2, index3 = 2

2.所查找的数组中只有一个元素 x,bisect_left 返回对应的索引,bisect_right 返回对应的索引 +1。

python 复制代码
import bisect

ls = [1,5,9,13,17]
index1 = bisect.bisect(ls,9)
index2 = bisect.bisect_left(ls,9)
index3 = bisect.bisect_right(ls,9)
print("index1 = {}, index2 = {}, index3 = {}".format(index1, index2, index3))
# index1 = 3, index2 = 2, index3 = 3

3.所查找数组中有多个 x,bisect_left 返回最左边的索引,bisect_right 返回最右边的索引 +1。

python 复制代码
import bisect

ls = [1,5,5,5,17]
index1 = bisect.bisect(ls,5)
index2 = bisect.bisect_left(ls,5)
index3 = bisect.bisect_right(ls,5)
print("index1 = {}, index2 = {}, index3 = {}".format(index1, index2, index3))
# index1 = 4, index2 = 1, index3 = 4

思路:

测试样例:

A[i] :1 3 5 7 9

B[j] : 3 5 7 9 11

C[k]: 5 7 9 11 13

结果:

a = bisect.bisect_left(A, B[j]) = 3

c = n - bisect.bisect_right(C, B[j]) =5- 2 = 3

由此找出A中<7的数的数量,和C中>7的数的数量。

同理:当B[j]=8时,因为8不在A与C中,a与c是在A与C中"合适的插入点索引,使得数组有序"。

所以a=4,c=5-2=3。

代码如下:

python 复制代码
import bisect
n = int(input())
A = list(map(int, input().split()))
B = list(map(int, input().split()))
C = list(map(int, input().split()))

A.sort()
B.sort()
C.sort()
ans = 0

for j in range(n):
    a = bisect.bisect_left(A, B[j])
    c = (n - bisect.bisect_right(C, B[j]))
    ans += a * c
print(ans)

连号区间数

在没有重复元素的情况下,连号区间等价于:区间内最大值-最小值==区间长度-1

代码如下:

python 复制代码
n = int(input())
a = list(map(int, input().split()))

ans = 0
for i in range(n):
    max_num = float('-inf')
    min_num = float('inf')
    for j in range(i, n):
        max_num = max(max_num, a[j])
        min_num = min(min_num, a[j])
        if max_num - min_num == j - i:
            ans += 1
print(ans)

螺旋矩阵

代码如下:

python 复制代码
n, m = map(int, input().split())
r, c = map(int, input().split())

a = [[0] * m for _ in range(n)]
x, y = 0, 0
value = 1
a[x][y] = value
while value < n * m:
    #向右
    while y + 1 < m and a[x][y + 1] == 0:
        value += 1
        y += 1
        a[x][y] = value
    #向下
    while x + 1 < n and a[x + 1][y] == 0:
        value += 1
        x += 1
        a[x][y] = value
    #向左
    while y - 1 >= 0 and a[x][y - 1] == 0:
        value += 1
        y -= 1
        a[x][y] = value
    #向上
    while x - 1 >= 0 and a[x - 1][y] == 0:
        value += 1
        x -= 1
        a[x][y] = value
print(a[r - 1][c - 1])

图像模糊

代码如下:

python 复制代码
n, m = map(int, input().split())
a = []
for _ in range(n):
    a.append(list(map(int, input().split())))
b = [[0] * m for i in range(n)]

dic = [(0, 0), (0, -1), (-1, -1), (-1, 0), (-1, 1), (0, 1), (1, 1), (1, 0), (1, -1)]

for i in range(n):
    for j in range(m):
        sum_num = 0
        num = 0
        for k in range(9):
            x, y = i + dic[k][0], j + dic[k][1]
            if 0 <= x < n and 0 <= y < m:
                sum_num += a[x][y]
                num += 1
        b[i][j] = sum_num // num
for i in range(n):
    print(' '.join(map(str, b[i])))

打印大X

代码如下:

python 复制代码
m, n = map(int, input().split())
lst = [["."] * (m + n - 1) for _ in range(n + 1)]

for i in range(n):
    for j in range(m):
        #副对角线
        lst[i][i + j] = '*'
        #正对角线
        lst[i][m + n - 2 - i - j] = '*'

for i in range(n):
    print(''.join(lst[i]))

等差素数列

代码如下:

我自己写的代码(能跑出来答案但是不太规范)

python 复制代码
import math
def sus(n):
    for i in range(2, int(math.sqrt(n)) + 1):
        if n % i == 0:
            return False
    return True

for i in range(2, 10000):
    if sus(i):
        for k in range(1, 500):
            a = [0] * 10
            a[0] = i
            for j in range(9):
                if sus(a[j] + k):
                    a[j + 1] = a[j] + k
                else:
                    break
            if a[9] != 0:
                print(k)

标准代码:

python 复制代码
import math
def is_prime(n):
    if n < 2:
        return False
    for i in range(2, int(math.sqrt(n)) + 1):
        if n % i == 0:
            return False
    return True

# 添加一个标志位
found = False

# 搜索长度为10的等差素数数列
for start in range(2, 10000):  # 起始素数
    if found:  # 如果已经找到,跳出外层循环
        break
    if is_prime(start):
        for diff in range(1, 500):  # 公差
            # 检查是否能构成长度为10的等差数列
            is_valid = True
            for j in range(1, 10):  # 只需要检查后续9个数
                if not is_prime(start + j * diff):
                    is_valid = False
                    break
            # 如果找到了,输出结果并设置标志位
            if is_valid:
                print(diff)
                found = True  # 设置标志位
                break  # 跳出内层循环

分巧克力

代码如下:

python 复制代码
n, k = map(int, input().split())

a = []
for i in range(n):
  h, w = map(int, input().split())
  a.append((h, w))

def check(x):
  cnt = 0
  for h, w in a:
    cnt += (h // x) * (w // x)
  if cnt >= k:
    return True
  else:
    return False

left, right = 1, 100000
ans = 1
while left <= right:
  mid = (left + right) // 2
  if check(mid):
    ans = mid
    left = mid + 1
  else:
    right = mid - 1
print(ans)

航班时间

思路:时差可以被消掉 ,例如我们假设a,b两地的时差为t 当飞机在a地 t1 时刻起飞此时b地的时间为t1+t 我们假设需要经过B时间飞机能从a->b则飞机到b地的时间为 t1+t+B ,题目给力我们飞机到b地的时间是t2则 t2=t1+t+b ,同样我们可以推导出 t3-t+B=t4 其中t3是飞机从b地起飞的时间t4是飞机到a地的时间 ,两者相加就把时差t给消掉了

python 复制代码
#将时间t换算成秒
def transfer(t):
    #也就是时间后面有括号,即跨天
    if len(t.split()) > 1:
        t1, t2 = t.split()#t1是正常时间,t2是(+1)
        t2 = int(t2[2]) * 24 * 3600#t2[2]就是括号里的数字
        t1 = transfer(t1)
        return t1 + t2
    else:
        t = t.split(":")
        return int(t[0]) * 3600 + int(t[1]) * 60 + int(t[2])

n = int(input())
for _ in range(n):
    #maxsplit旨在只算前面的两个正常时间
    t1, t2 = input().split(maxsplit = 1)
    t3, t4 = input().split(maxsplit = 1)
    t = (transfer(t2) + transfer(t4) - transfer(t1) -transfer(t3)) // 2
    hour = t // 3600
    minute = t % 3600 // 60
    second = t % 3600 % 60
    print("%02d:%02d:%02d" % (hour, minute, second))

移动距离

代码如下:

python 复制代码
import math
#计算扇形半径
r = math.sqrt(233 ** 2 + 666 ** 2)
#计算扇形弧度
hu = math.atan(666 / 233)
#弧长 = 半径 * 弧度
l = hu * r
print(round(l + r))

移动距离

python 复制代码
w, m, n = map(int, input().split())

def get_position(num):
    # 行号(0-based)
    row = (num - 1) // w
    # 列号(0-based)
    if row % 2 == 0:  # 偶数行,从左到右
        col = (num - 1) % w
    else:  # 奇数行,从右到左
        col = w - 1 - (num - 1) % w
    return row, col

# 获取m和n的坐标
row_m, col_m = get_position(m)
row_n, col_n = get_position(n)

# 计算曼哈顿距离
distance = abs(row_m - row_n) + abs(col_m - col_n)
print(distance)

蚂蚁感冒

关键观察:

蚂蚁碰头后掉头,相当于它们互相穿过但交换身份(包括感冒状态)。

所以本质上可以认为蚂蚁保持原方向不变,只是穿过时交换了"标签"。

那么感冒传播就变成了:感冒蚂蚁在原方向上走,所有与它方向相对、且在它前进路径上会相遇的蚂蚁都会被感染。

两种情况(以第一只蚂蚁方向分):

  1. 第一只蚂蚁向右(正数):

· 它在它右边且向左走的蚂蚁,一定会被它感染(因为它们相向而行)。

· 然后这些被感染的蚂蚁中,如果它们在原第一只蚂蚁的左边且向右走,这些也会被感染(因为它们和被感染的蚂蚁相向而行)。

· 所以计算方法是:

· 右边向左的蚂蚁数 = right_to_left

· 左边向右的蚂蚁数 = left_to_right

· 总感冒数 = 1 + right_to_left + (如果 right_to_left > 0 则加 left_to_right 否则不加)

  1. 第一只蚂蚁向左(负数):

· 它在它左边且向右走的蚂蚁,一定会被感染。

· 然后这些被感染的蚂蚁中,如果它们在原第一只蚂蚁的右边且向左走,也会被感染。

· 所以计算方法是:

· 左边向右的蚂蚁数 = left_to_right

· 右边向左的蚂蚁数 = right_to_left

· 总感冒数 = 1 + left_to_right + (如果 left_to_right > 0 则加 right_to_left 否则不加)

代码如下:

python 复制代码
n = int(input())
ants = list(map(int, input().split()))
first = ants[0]
ans = 0

left_to_right = 0
right_to_left = 0

for ant in ants[1:]:
    if ant < 0 and abs(ant) > abs(first):
        right_to_left += 1
    elif ant > 0 and abs(ant) < abs(first):
        left_to_right += 1

if first > 0:
    if right_to_left > 0:
        ans = 1 + right_to_left + left_to_right
    else:
        ans = 1
else:
    if left_to_right > 0:
        ans = 1 + left_to_right + right_to_left
    else:
        ans = 1
print(ans)
相关推荐
sali-tec1 小时前
C# 基于OpenCv的视觉工作流-章39-FL特征匹配
图像处理·人工智能·opencv·算法·计算机视觉
好家伙VCC2 小时前
# 发散创新:用 Rust构建高并发虚拟世界引擎核心模块在当今游戏开发与元宇宙构建中,**虚拟世界的性能瓶颈往往不是图形渲染,而是底
java·开发语言·python·rust·图形渲染
Liu628882 小时前
C++中的状态模式
开发语言·c++·算法
smchaopiao2 小时前
使用C语言打印几何图形:从三角形到菱形
c语言·开发语言·算法
又菜又爱编程的小白2 小时前
L1-071 前世档案
c++·算法·天梯赛
赵长辉2 小时前
牛客面试Top101: BM8 表达式求值【java,go】
算法·面试
for_syq2 小时前
trace抓取工具
android·python
Wave8452 小时前
数据结构—线性表
数据结构
Tisfy2 小时前
LeetCode 3212.统计 X 和 Y 频数相等的子矩阵数量:前缀和
算法·leetcode·前缀和·矩阵