【python语言】第十四届蓝桥杯国赛 c/c++b组

一、子2023.

1. 考点:动态规划
2. 难度:⭐⭐⭐
3. 要点分析:

本题有两种做法,

(1)暴力求解。虽然时间复杂度挺高(跑了挺久),但在一定时间内是能够跑出正确答案的。

seq = ''
for i in range(1,2023+1):
    seq += str(i)

s = ''
for t in seq:
    if t in ['2','0','2','3']:
        s += t

ans = 0
for i in range(len(s)):
    if s[i]=='2':
        for j in range(i+1,len(s)):
            if s[j]=='0':
                for p in range(j+1,len(s)):
                    if s[p]=='2':
                        for q in range(p+1,len(s)):
                            if s[q]=='3':
                                ans += 1
print(ans)

(2)动态规划。对于我本人来说比较难想一点,但确实开拓了一个新思路。

每多增加一个“2”,dp[0]+1,且对应的“202”的数目(dp[2])也会增加1*dp[1]个;

每多增加一个“0”,“20”的数目(dp[1])会增加1*dp[0]个;

每多增加一个“3”,“2023”的数目(dp[3])会增加多1*dp[2]个。

seq = ''
for i in range(1,2023+1):
    seq += str(i)

s = ''
for t in seq:
    if t in ['2','0','2','3']:
        s += t

"""分别代表 2 20 202 2023"""
dp = [0]*4
for t in s:
    if t=='2':
        dp[0] += 1
        dp[2] += dp[1]
    if t=='0':
        dp[1] += dp[0]
    if t=='3':
        dp[3] += dp[2]
print(dp[-1])

【考试时实在不行第一种,但练习时要学习第二种哈哈哈~】

二、双子数。

1. 考点:质因子分解
2. 难度:⭐⭐
3. 要点分析:

①在双层循环中,若不增加一些“筛选条件”,或是从start~end开始循环,时间复杂度都会比较大。

import math

def check(x):
    for i in range(2,int(math.sqrt(x))+1):
        if x%i==0:
            return 0
    return 1

"""将x开方 变为p*q的数 找到其中的p和q"""
start = int(math.sqrt(2333))
end = int(math.sqrt(23333333333333))

prime = [2,]
for i in range(3,end+1):
    if check(i):
        prime.append(i)

vis = [0]*(end+1)
for p in range(len(prime)):
    for q in range(p+1,len(prime)):
        x = prime[p]*prime[q]
        if x>end:
            break
        if x<start:
            continue
        vis[x] = 1
print(sum(vis[start:]))

②尽管本次不需要对“素数的判断”进行优化,但还是记住“欧拉筛”比较好,说不定下次能够用上。其基本思想是,素数的倍数不是素数。

def ouler(r):
    primes = []
    check = [True for i in range(r+1)]
    for i in range(2,r+1):
        if check[i]:
            primes.append(i)
        for j in primes:
            if i * j > r:
                break
            check[i*j] = False
            if i % j == 0:
                break
    return primes

三、班级活动。

1. 考点:思维
2. 难度:⭐⭐⭐
3. 要点分析(详细解析可参考):考虑清楚“可配对”的情况:①id数等于1的学生自由配对;②id数超过2的学生全部改变;③id数等于1的学生和id数超过2的学生配对,仅需改变id数超过2的学生的id。由此,结合“最少变动”,得出改变方案。

【洛谷 P9421】[蓝桥杯 2023 国 B] 班级活动 题解(计数排序+贪心算法+数学)-CSDN博客

n = int(input())
numbers = list(map(int, input().split()))
ds = dict()

"""
有可能会出现同一数字出现多次的情况
每个数字只能出现两次 多于两次则需要更改
"""

# 统计次数
for t in numbers:
    if t not in ds.keys():
        ds[t] = 1
    else:
        ds[t] += 1

x = 0   #待分配id的学生
y = 0   #id重复的学生
for t in list(ds.keys()):
    if ds[t] == 1:
        x += 1
    elif ds[t] > 2:
        y += ds[t]-2

# x<=y 只需要改变id重复的学生即可
if x<=y:
    print(y)
# x>y 1.改变id重复的学生以适配;2.剩余待分配学生两两配对
else:
    print((x-y)//2+y)

四、合并数列。

1. 考点:模拟、双指针
2. 难度:⭐⭐⭐
3. 要点分析:

①利用“双指针”时,不要改变指针指向的数组的内容;而是选择另一个衡量标准——“当前的数组和是否相等”。

②当使用“while循环”时,需格外注意其循环条件:有可能p==n-1,但此时q!=(m-1)且sumA!=sumB。但两个数组的数组和必然是相等的,因此只需要再合并数组余下的数即可。

n, m = map(int, input().split())
a = list(map(int, input().split()))
b = list(map(int, input().split()))

p=0;q=0
sumA=0;sumB=0
ans = 0
while p<n and q<m:
    if sumA==sumB:
        sumA += a[p]
        sumB += b[q]
        p+=1;q+=1
    elif sumA<sumB:
        sumA += a[p]
        p += 1
        ans += 1
    elif sumA>sumB:
        sumB += b[q]
        q += 1
        ans += 1
print(ans+n+m-p-q)

五、数三角。

1. 考点:枚举
2. 难度:⭐⭐⭐
3. 要点分析:该题解在pyp3能过,python只能达到65%。

①对于平面上的每一个点P,计算其与其它所有点的距离。

②以P点位顶点,计算其与其它两点能否构成三角形。

注:本题的思路不难,难在“优化”上;如何减少代码的时间复杂度。

import math

n = int(input())
dots = []
for i in range(n):
    x, y = map(int, input().split())
    dots.append([x,y])
    
ans = 0
# 以p点为圆心,记录不同点与点p的距离
for p in range(n):
    dockers = {}
    for q in range(n):
        if p==q:
            continue
        x1,y1 = dots[p]
        x2,y2 = dots[q]
        dis = math.sqrt((x1-x2)**2+(y1-y2)**2)
        if dis not in dockers:
            dockers[dis] = [q]
        else:
            dockers[dis].append(q)
    
    for dis in dockers:
        if len(dockers[dis])>=2:
                # 判断是否能组成三角形
                for i in range(len(dockers[dis])):
                    for j in range(i+1,len(dockers[dis])):
                        x1,y1 = dots[dockers[dis][i]]
                        x2,y2 = dots[dockers[dis][j]]
                        tmp = math.sqrt((x1-x2)**2+(y1-y2)**2)
                        if tmp < 2*dis:
                            ans += 1
print(ans)
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值