第十三届蓝桥杯国赛真题 PythonB组 复盘以及获奖感言(国一!!!)

第十三届蓝桥杯国赛真题 PythonB组 复盘以及获奖感言(国一)


img

🏆 获奖感言

国一开心! 国一开心! **国一开心!**重要的词说三遍,这个国赛确实让我有点惊喜,我居然拿到国赛一等奖!!!

从今年年初开始,慢慢的捡起曾经的数据结构的知识以及很多算法的知识,努力学习,在5月的时候,成功拿到了省一等奖,当时其实我都感觉我要凉了,感觉彻底没什么希望了,只希望自己能够拿一个省二吧,但是我的目标一开始就是国赛,不过不是国一,而是国二。

我和我的朋友努力学习,互相交流,我觉得在打比赛的时候,在学习的时候,有一个志同道合的朋友是很好的,也有很多人会加群,然后不断交流学习,这样的学习方式我感觉是不错的,大家可以互相思考,互相借鉴对方的思路,互相分享一些不错的知识点,这样我们就可以达到教学相长也的情况,而且大家也是一起努力的,一起比赛,最后我和我朋友分别我是国一,他国二,可谓是皆大欢喜。

其实蓝桥杯相对很多赛事来说,获奖的比例还是高的,比如在省一,可以有70%的人获奖,当然省一只有10%,在国赛,取前5%的为国一,15%为国二,20%为国三,不过实际上是加和的,也就是5+15+20=45,国赛有45%获奖,其他人只要不是0分都可以评个简单的优秀奖,不虚此行哈哈哈

随着时代的发展,蓝桥杯也不再是暴力杯了,特别今年开始,填空题只有2道,投机取巧的机会比较少了,我省一填空题只作出一道,但是国赛填空题好像一道都没有对,感觉还是慢慢变难了,也听说A组的题目也是很难的,所以慢慢蓝桥杯也调整了题目的分布和难度,而不仅仅是暴力搜索的解题,但是不可置疑的是,暴力解题还是可以得到一部分的分的。

总的来说,这次蓝桥杯之行还是圆满的,拿到了国赛的一等,为我的前途铺了层砖,也希望之后的大家也努努力,你们也一定可以的

试题A: 斐波那契与7

在这里插入图片描述

思路

这道题来说,其实看起来是很简单的,所以我想的也很简单,就是穷举,然后%10,最后一项为7的就+1,但是这个数据太大了,我运行了好久好久都没有出来,最后我利用C++去写这道题,然后也运行了2h以上,得到一个答案。

但是后面我发现,如果每次加的时候都%10,得到的结果不一定是正确的,所以最后这道题我应该是错误的,填空题,太难了呀,这穷举不出来啊。本来还想着用快速幂,不过最后还是放弃了。

代码

a,b=1,1
n = 202202011200
ans = 0
for i in range(n-2):
    a,b = b%10,(a+b)%10
##    print(b)
    if b%10 == 7:
        ans += 1
print(ans)

试题B: 小蓝做实验

在这里插入图片描述

思路

这道题来说,很简单,利用线性筛或者是埃氏筛,但是问题就是,我用了线性筛,虽然对于线性筛来说,我们的计算素数是很快的,但是整个数据其实还是很大很大,我朋友跟我说,其实我们先应该筛选,这个范围是10的3次方到10的12次方,总的来说,就是数据太大,用的方法稍微的有点不对劲,结果还是没跑出来,我python真的很久,绝望!!!

代码

n = 100000000
isprime = [False]*(n+1)
primes = [0]*(n+1)
cnt = 0

for i in range(2,n):
    if not isprime[i]:
        primes[cnt] = i
        cnt += 1
    for j in range(cnt):
        if i*primes[j] > n: break
        isprime[i*primes[j]] = True
        if i%primes[j] == 0: break
primes = primes[:cnt]

res = 0
f = open('primes.txt')
data = f.readlines()
print(len(data))
for i in range(len(data)):
    x = data[i].replace('/n','')
    x = int(x)
    if x in primes:
        res += 1
    if i%1000 == 0:
        print(i,res)
print(res)

试题C: 取模

在这里插入图片描述

样例输入

3
1 2
5 2
999 99

样例输出

No
No
Yes

提示

对于 20% 的评测用例,T ≤ 100 ,n, m ≤ 1000;

对于 50% 的评测用例,T ≤ 10000 ,n, m ≤ 105;

对于所有评测用例,1 ≤ T ≤ 105 ,1 ≤ n ≤ 109 ,2 ≤ m ≤ 109。

思路

这道题完全没有什么思路,直接暴力即可,时间有限,还不如做下一道题

(后面来看,暴力还是能拿一半的分的,不亏不亏 https://www.dotcpp.com/oj/problem2735.html)

代码

t = int(input())
for i in range(t):
    n,m = map(int,input().split())
    flag = False
    for x in range(1,m):
        for y in range(x+1,m+1):
            if n%x == n%y:
                flag = True
                break
        if flag:
            break
    if flag:
        print('Yes')
    else:
        print('No')

试题D:内存空间

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SUiQHcY0-1656651026729)(C:\Users\86137\AppData\Roaming\Typora\typora-user-images\image-20220701111108884.png)]

在这里插入图片描述

样例输入1

1
long[] nums=new long[131072];

样例输出1

1MB

样例输入2

4
int a=0,b=0;
long x=0,y=0;
String s1=”hello”,s2=”world”;
long[] arr1=new long[100000],arr2=new long[100000];

样例输出2

1MB538KB546B

在这里插入图片描述

思路

这道题,我觉得单纯就是对字符串进行一个操作,我们可以看到有两种类型,我们分别对两种类型进行操作

不过每一种类型来说,首先,我们都是要将我们的数据分开,相同的特点就是,他们都是以逗号进行分割的,所以我们可以用split(‘,’)很简单的分开。然后根据不同的int,char以及string来判断字符的大小和长度即可。

对于第二种类型来说,稍微复杂一点,但是思路还是很清晰的,就是我们可以找到左右两个中括号,然后对立面进行计数,而且他仅仅有两种类型,分别是int和long,这样的判断就更简单了。

最后我们可以得到我们的空间大小,但是我们需要进行化简,根据1GB=1024MB,1MB=1024KB,1KB=1024B,得到最后的结果,可以说,这道题是我比较有信心的题。

代码

t = int(input())

res = 0
for i in range(t):
    s = input()
    if '[]' in s:
        a = s.split(',')
        # print(a)
        if s[0] == 'i':
            for x in a:
                left = x.rfind('[')
                right = x.rfind(']')
                ans = int(x[left+1:right])
                print(ans)
                res += ans*4
            pass
        elif s[0] == 'l':
            for x in a:
                left = x.rfind('[')
                right = x.rfind(']')
                ans = int(x[left+1:right])
                res += ans*8
    else:
        a = s.split(' ')
        tp,var = a[0],a[1]
        if tp == 'int':
            x = len(a[1].split(','))
            res += x*4
        elif tp == 'long':
            x = len(a[1].split(','))
            res += x*8
        elif tp == 'String':
            x = a[1].split(',')
            for y in x:
                res += len(y.split('=')[1]) - 2
            res -= 1     
GB = res//(1024*1024*1024)
MB = res//(1024*1024) - GB*1024
KB = res//(1024) - GB*1024*1024 - 1024*MB
B = res%1024
if GB != 0:
    print('%dGB'%GB,end='')
if MB != 0:
    print('%dMB'%MB,end='')
if KB != 0:
    print('%dKB'%KB,end='')
if B != 0:
    print('%dB'%B,end='')

试题E: 近似GCD

在这里插入图片描述

在这里插入图片描述

样例输入

5 3
1 3 6 4 10

样例输出

5

提示

满足条件的子数组有 5 个:

[1, 3]:将 1 修改为 3 后,这个子数组的最大公约数为 3 ,满足条件。

[1, 3, 6]:将 1 修改为 3 后,这个子数组的最大公约数为 3 ,满足条件。

[3, 6]:这个子数组的最大公约数就是 3 ,满足条件。

[3, 6, 4]:将 4 修改为 3 后,这个子数组的最大公约数为 3 ,满足条件。

[6, 4]:将 4 修改为 3 后,这个子数组的最大公约数为 3,满足条件。

对于 20% 的评测用例,2 ≤ n ≤ 102;

对于 40% 的评测用例,2 ≤ n ≤ 103;

对于所有评测用例,2 ≤ n ≤ 105 ,1 ≤ g, ai ≤ 109。

思路

这道题来说的话,其实有点复杂,我也不知道我的算法对不对。我一开始想着是否可以用DP解决,但是没有一个固定的思路,最后我直接穷举两端,然后对数据进行求gcd,如果发现有数据算出来不是期望的g,那我就进行修改,如果修改两次,就直接退出,说明这个子数组是不符合的。

这道题最后,应该也是暴力得了些许分,肯定不是满分的,也可以去测试一下https://www.dotcpp.com/oj/problem2727.html

代码

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

from math import gcd
res = 0
for i in range(n-1):
    for j in range(i+1,n):
        x = a[i:j+1]
        ans = g
        flag = True
        flag2 = True
        # 判断所有的和
        for y in x:
            if y%g != 0:
                if flag:
                    flag = False
                    y = g
                else:
                    flag2 = False # 修改第二次
                    break
            ans = gcd(ans,y)
            if ans != g:
                break
        # print(x,ans)
        if ans == g and flag2:
            res += 1

print(res)

试题F: 交通信号

在这里插入图片描述

样例输入

4 4 1 4
1 2 1 2 6
4 2 1 1 5
1 3 1 1 1
3 4 1 99 1

样例输出

11

思路

这道题其实可以用迪杰斯特拉算法,构建双向边进行求解,但是考试的时候并没有想出来,所以最简单的可以拿分的就是,print(-1)

代码

print(-1)

试题G: 点亮

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

思路

没思路,写不出来,不过可以穷举2x2的方格捞分

代码

暂无

试题H: 打折

在这里插入图片描述

样例输入

2 2
1 2 89 1
1 97
3 4 77 1
2 15

样例输出

101

提示

对于 40% 的评测用例,n, m ≤ 500 ,si ≤ ti ≤ 100 ,∑ ci ≤ 200000 ;

对于 70% 的评测用例,n, m ≤ 5000 ,∑ ci ≤ 200000 ;

对于所有评测用例,1 ≤ n, m ≤ 100000,1≤ ci≤ n , ∑ ci ≤ 400000 ,1 ≤ si ≤ ti ≤ 109 ,1 < pi < 100 ,1 ≤ aj ≤ n ,1 ≤ bj ≤ 109 。

思路

这道题,就是一个暴力,找一下每个时间段中费用最低的,然后全部买一遍,最后遍历取最大的结果

这应该不是正解,但是考试的时间那时候还是比较紧张,我就先简单暴力写一下。

这道题最后,应该也是暴力得了些许分,肯定不是满分的,也可以去测试一下https://www.dotcpp.com/oj/problem2730.html

代码

n,m = map(int,input().split())
from collections import defaultdict
prices = defaultdict(list)
days = 0
for i in range(n):
    s,t,p,c = map(int,input().split())
    days = max(days,t)
    for j in range(c):
        a,b = map(int,input().split())
        price = b*p//100
        prices[a].append([price,s,t])
        prices[a].append([b])

##print(prices)
min_price = float('inf')
for day in range(days):
    res = 0
    for k,v in prices.items():
        v.sort()
        # print(v)
        for p in v:
            if len(p) == 3:
                if p[1] <= day <= p[2]:
                    ans = p[0]
                    break
            else:
                ans = p[0]
                break
        res = res + ans
##        print(res)
    min_price = min(res,min_price)
print(min_price)

试题I: owo

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

思路

这道题的思路也是穷举,但是这里面用了一下全排列函数,然后将数据排序,判断最长的结果。

时间有限,也没想好有什么好的方法,不过这个肯定能拿10+分的,40+分不知道有没有机会

代码

n = int(input())

def get_owo(sr):
    l = len(sr)
    x = sr.find('owo')
    ans = 0 
    if x == -1:
        return 0
    else:
        ans = 1
    for i in range(x+2,l,2):
        # print(sr[i:i+3])
        if sr[i:i+3] == 'owo':
            ans += 1

    return ans

a = []
from itertools import permutations
for i in range(n):
    s = input()
    a.append(s)
    res = 0
    b = list(set(permutations(a)))
    for x in b:
        sr = ''.join(x)
##        print(sr)
        ans = get_owo(sr)
        res = max(res,ans)
    print(res)

试题J: 替换字符

在这里插入图片描述

样例输入

abcaaea
4
1 7 c e
3 3 e b
3 6 b e
1 4 a c

样例输出

cbecaea

提示

对于 40% 的评测用例,|s|, m ≤ 5000;

对于所有评测用例,1 ≤ |s|, m ≤ 105 ,1 ≤ li ≤ ri ≤ |s| ,xi 不等于 yi ,其中 |s| 表示字符串 s 的长度。

思路

这道题,直接就是区间修改,感觉是线段树,但是好像模板套的又不是很可以,之后就没有一个很好的想法了

最后利用python将部分字母进行替换,我们就可以直接用replace,用replace就可以简单的过了一部分的数据,应该是40%的数据

这道题最后,应该也是暴力得了些许分,也可以去测试一下https://www.dotcpp.com/oj/problem2739.html

代码

s = input()

n = int(input())

for _ in range(n):
    l,r,x,y = input().split()
    l,r = int(l),int(r)
    tmp = s[l-1:r].replace(x,y)
##    print(tmp)
    s = s[:l-1] + tmp + s[r:]
    # print(s)
print(s)
  • 7
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风信子的猫Redamancy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值