2025年_第16届蓝桥杯pyB组

(A、C、D、E、F、G题已得到洛谷的验证,答案全部正确。H题还没想明白,先暴力骗分)


(题(提)前声明:本人属于匕首(菜鸡~.~)水平,自己手写的题解,望各位佬批评指正,京津冀赛事延期,看看别的省的题)

A:攻击次数

n = 0
i = 1
while n < 2025:
    if i & 1:
        n += 15
    else:
        if i % 3 == 2:
            n += 10
        elif i % 3 == 0:
            n += 7
        else:
            n += 5
    i += 1
print(i - 1)
# print(181)

(这道题有歧义的地方为:三个英雄能否同时攻击,本题解考虑的为不能同时攻击)


挑攻击力大的技能使用即可,可见:奇数一定使用第二个英雄的技能,然后偶数情况的话模3余1用第一个英雄技能,其他情况用第三个英雄的技能。

B:最长字符串

(B题的文件没有找到,暂时省略,后期有的话补充。。。。)

C:LQ图形

w,h,v = MII()
t = h
b = w
for i in range(t):
    print('Q' * w)
for i in range(b):
    print('Q' * (v + w))

画图形的题,类似于画其他有规律的图形,观察可发现,可以将L分为上下两个部分,上面列数少的为h行,下面列数多的为w行,上下宽度分别为w和v+w。时间复杂度O(h + w)

D:最多次数

s = list(I())
n = len(s)
i = 0
res = 0
while i < n:
    if s[i] in ['l','q','b']:
        f = defaultdict(int)
        j = 0
        while j + i < n and j < 3:
            f[s[j + i]] = 1
            j += 1
        if f['l'] == 1 and f['q'] == 1 and f['b'] == 1:
            res += 1
            i += 2
    i += 1
print(res)

 贪心:遇到连续的三个某个顺序的l,q,b,就把他拿掉。时间复杂度O(n)

E:A · B Problem

n = II()
f = [0] * (n + 2)
for i in range(1,n + 1):
    for j in range(i,n + 1,i):
        f[j] += 1

pre = [0] * (n + 2)
for i in range(1,n + 1):
    pre[i] = pre[i - 1] + f[i]


res = 0
for i in range(1,n + 1):
    res += f[i] * pre[n - i]
print(res)

优先找到所有L的因数的个数,然后求出所有因子的前缀和,(例如:6可以被分解为4个因数对(1,6),(2,3),(3,2),(6,1)),然后最后求的是相加为L的种类数,所以直接相乘即可。

时间复杂度:O(nlogn)

(计算因子的两层循环是调和级数,复杂度为O(nlogn),可以记一下。2^20大约是10^6)

(调和级数是这个样子:n*(\frac{1}{n} + \frac{2}{n} + .... + \frac{n}{n} ),括号内这一部分可以用微积分求出为log级别)

F:园艺

n = II()
h = LII()
res = 1
for d in range(1,n):
    di = (n + d - 1) // d
    if di <= res:
        break

    for i in range(n):
        tot = 1
        prev = h[i]
        cmx = 1
        k = 1
        while i + k * d < n:
            cnt = h[i + k * d]
            if cnt > prev:
                tot += 1
                cmx = max(cmx,tot)
            else:
                tot = 1
            prev = cnt
            k += 1
        res = max(res,cmx)
print(res)

题目要求间隔相同,并且高度严格递增,所以这是一道等间隔最长上升子序列问题

第一层循环d是跳跃的步数,第二层循环是开始的元素位置,while循环是按照步数寻找等间隔的元素,tot是当前的最长序列长度,cmx是步数为d时的最长序列长度,prev是前一个元素的值。

时间复杂度:O(n²logn)(大致算了一下,n为5000时,大概为3*10^8,不过因为有早停策略,并且d越大就越早结束,实际情况到不了这么大,这里就不细算了,感兴趣的code友可以算算)

(第二个for+while循环又是调和级数的复杂度)

G:书架还原

n = II()
a = [0] + LII()
p = [0] * (n + 1)
res = 0
for i in range(1,n + 1):
    p[a[i]] = i

for i in range(1,n + 1):
    if a[i] != i:
        p[a[i]] = p[i]
        a[i],a[p[i]] = a[p[i]],a[i]
        res += 1

print(res)

贪心,总处理次数为所有环的长度减一的和(判环可以用标记法进行判断,也是O(n))

时间复杂度:O(n)

H:异或和

 这道题没写,想着暴力骗点分完事了,后来观察到a的数据范围只有2^20,大约10^6,而且题目中是求异或运算,所以一定和位运算有关系,大概要创建一个二维数组dp[n][21],然后进行计算。

(没写了,后边补吧。。。。)

时空复杂度应该都是:O(20 * n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值