蓝桥杯算法笔记(一)

文章讲述了如何使用两种方法计算列表中连续子数组之和被K整除的个数,一种是暴力枚举,另一种是利用前缀和和贪心策略。同时介绍了如何快速计算两个矩形的重叠面积,提供了更高效的代码实现。
摘要由CSDN通过智能技术生成

 k倍区间

将输入第二行存储到一个列表之中,以第一个元素为起点,依次连续做累加,各种情况的和判断是否为k的倍数。

1. 首先,从输入中获取两个整数 N 和 K。
2. 创建一个长度为 N 的列表 a,并初始化为全零。
3. 通过循环,将用户输入的 N 个整数依次存储到列表 a 中。
4. 使用两层循环遍历列表 a:
   外层循环变量 j 用于遍历列表a的索引。
   内层循环变量 i 初始化为 j,用于迭代计算连续子数组之和。
   变量 k 和 b 初始化为 a[j],表示当前子数组的和。
   在内层循环中,从当前位置开始向后累加子数组元素,如果累加和能被 `K` 整除,则 `num` 计数加一。
5. 最后输出计数结果 `num`,即连续子数组之和能被 `K` 整除的个数。

计算列表中连续子数组之和能被 `K` 整除的个数。

N,K=map(int,input().split())
a=[0 for i in range(N)]
num=0
for i in range(N):
  a[i]=int(input())
for j in range(N):
  k=a[j]
  b=k
  l=j
  while l < N:
    if b % K==0:
        num += 1
    if l < N-1:
        b += a[l+1]
    l+=1
print(num)

但是这样会导致运行时间过长,暴力枚举,实例不能完全通过,这时我们运用前缀和的性质。通过维护一个累加和 ans 和一个计数数组 cnt,计算了连续子数组之和能被 K 整除的个数。

1. 首先,从输入中获取两个整数 N 和 K。
2. 初始化变量 ans 和列表 cnt,列表 cnt 的长度为 K,并且所有元素初始化为 0。
3. 使用循环遍历N 次:
   从输入中获取一个整数 num。
   将 num 加到 ans 中。
   计算num 累加到 ans 后对 K 取余的结果,并将结果对应的 cnt 列表元素加一。
4. 将 ans 重新赋值为 cnt[0]。
5. 再次使用循环遍历 0 到 K-1:
   如果 cnt[i] 不为零,将 ans 加上 cnt[i] 乘以 cnt[i] - 1 再除以 2 的结果。
6. 最后输出计数结果ans,即连续子数组之和能被 K 整除的个数。

代码中维护了一个累加和ans,并且对 ans 求余数后将结果存储在列表cnt 中。这一步的目的是统计所有前缀和对 K 取余的结果,以便后续计算连续子数组之和能被 K整除的个数。

在第一步的基础上,代码进一步遍历 cnt 列表,对于每个余数 i,如果 cnt[i] 不为零,说明存在多个前缀和对 K 取余结果为 i。这里利用组合数学的思想,对于每个余数i,如果有 cnt[i] 个前缀和对 K 取余结果为 i,则可以从中选择两个前缀和,它们的和能被 K 整除。因此,对于每个余数 i,可以计算出 cnt[i] * (cnt[i] - 1) / 2 种组合情况,将这些情况累加到最终的结果中。

import os
import sys
N,K = map(int,input().split())
ans = 0
cnt = [0]*K
for i in range(N):
  num = int(input())
  ans += num
  cnt[ans%K] += 1
ans = cnt[0]
for i in range(0,K):
  if cnt[i]:
    ans += cnt[i] * (cnt[i] - 1)//2
print(ans)

这种算法思想在处理连续子数组问题中具有一定的普适性和高效性,能够在一定程度上提高问题的解决效率。

买二赠一

首先按照价格从低到高对商品进行排序,然后通过贪心算法的思想,每次购买两件商品中价格较低的那一件,并在剩余商品中找到价格不超过其一半的商品进行免费获得。重复这个过程直到所有商品都被购买或获得。最后计算总花费并输出结果。

import bisect

def min_cost_to_get_all_items(N, prices):
    prices.sort()  # 将商品价格列表按照从小到大排序
    total_cost = 0
    cnt = 0
    last = -1
    last_id = N - 1
    vis = [False] * N

    for i in range(N - 1, -1, -1):
        if not vis[i]:
            cnt += 1
            total_cost += prices[i]
            last = prices[i]

        if cnt == 2:
            cnt = 0
            x = bisect.bisect_left(prices, last // 2, 0, last_id)
            if x > last_id or prices[x] > last // 2:
                x -= 1
            if x >= 0:
                vis[x] = True
                last_id = x - 1

    return total_cost

# 读取输入
N = int(input())
prices = list(map(int, input().split()))

# 调用函数计算最小花费
result = min_cost_to_get_all_items(N, prices)
print(result)

1. min_cost_to_get_all_items函数接受两个参数:商品数量N和价格列表prices。该函数首先对价格列表进行排序,然后使用贪心算法的思想来计算购买所有商品所需的最小花费。
2. 在函数内部,通过循环遍历价格列表,对每个商品进行如下操作:
   如果商品未被购买过,则将其加入购买列表,并更新总花费。
   每购买两件商品时,找到价格不超过最后一件购买商品价格的一半的商品,并将其标记为已购买,更新下一次可免费获得商品的范围。
3. 最后,函数返回计算得到的总花费。

接着,读取输入的商品数量N和每件商品的价格列表,然后调min_cost_to_get_all_items函数计算并输出购买所有商品所需的最小花费。

n = int(input())
num = list(map(int,input().split()))
num.sort()
cost = sum(num)
cnt = 0
r = n-1
for i in range(n-1,-1,-1):
    if num[i] == 0:
        continue
    if cnt == 0:
        cnt+=1
        continue
    t = num[i]//2
    while (r>=0 and num[r]>t):
        r-=1
    if r<0:
        break
    cost-=num[r]
    num[r]=0
    r=r-1
    cnt = 0
print(cost)

另一种解决问题的方法,也是使用贪心算法的思想。(蓝桥杯题解里类似)

1. 首先,代码读取输入的商品数量n和每件商品的价格列表num,并对价格列表进行排序。
2. 初始化变量cost为所有商品价格的总和,初始化变量cnt为0,初始化变量r为n-1。
3. 通过逆序遍历价格列表,对每个商品进行如下操作:
   如果商品价格为0,则跳过当前商品。
   如果cnt为0,则表示当前需要购买商品,将cnt增加1并继续下一个商品。
   计算当前商品价格的一半t,然后在剩余商品中找到价格不超过t的商品,将其标记为已购买(价格设为0),更新总花费cost,并更新下一次可免费获得商品的范围r。
4. 最后输出计算得到的总花费cost,即购买所有商品所需的最小花费。

但是该问题贪心算法并不是最优解,比如6 12 23 25 25 50 50 正确答案是156。

矩阵总面积

1. 首先,R1的左下角坐标为(x1, y1),右上角坐标为(x2, y2)。R2的左下角坐标为(x3, y3),右上角坐标为(x4, y4)。
   
2. 矩形R1的面积为:Area_{R1} = (x2 - x1) \times (y2 - y1)。矩形R2的面积为:Area_{R2} = (x4 - x3) \times (y4 - y3)。

3. 重叠部分的面积:重叠部分的左下角坐标为(max(x1, x3), max(y1, y3)),右上角坐标为(min(x2, x4), min(y2, y4))。
   如果重叠部分的左下角横坐标小于右上角横坐标且纵坐标小于右上角纵坐标,则说明有重叠部分,计算重叠部分的面积。重叠部分的面积为:Overlap_{Area} = (min(x2, x4) - max(x1, x3)) \times (min(y2, y4) - max(y1, y3))。

4. 最后,计算两个矩形的总面积:
   总面积为:Total_{Area} = Area_{R1} + Area_{R2} - Overlap_{Area}。

def calculate_area(x1, y1, x2, y2, x3, y3, x4, y4):
    # 计算矩形R1的面积
    area_R1 = (x2 - x1) * (y2 - y1)
    # 计算矩形R2的面积
    area_R2 = (x4 - x3) * (y4 - y3)
    # 计算重叠部分的面积
    overlap_x1 = max(x1, x3)
    overlap_y1 = max(y1, y3)
    overlap_x2 = min(x2, x4)
    overlap_y2 = min(y2, y4)
    overlap_area = max(0, overlap_x2 - overlap_x1) * max(0, overlap_y2 - overlap_y1)
    # 计算总面积
    total_area = area_R1 + area_R2 - overlap_area
    return total_area
# 读取输入
x1, y1, x2, y2, x3, y3, x4, y4 = map(int, input().split())
# 计算总面积
result = calculate_area(x1, y1, x2, y2, x3, y3, x4, y4)
print(result)

更加简单,运行速度更快的代码(蓝桥杯题解里)

import os
x1,y1,x2,y2,x3,y3,x4,y4 = map(int,input().split())
m =  (x2-x1)*(y2-y1) + (x3-x4)*(y3-y4)
if (x2<x3 or x4<x1 or y2<y3 or y4<y1):
    print(m)
else:
    x_c = abs(min(x2, x4) - max(x1, x3))
    y_c = abs(min(y2, y4) - max(y1, y3))
    m -= x_c*y_c
print(m)

有问题欢迎大家指出,小编持续更新中,,,

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值