2022蓝桥杯A组Python

更新,江苏赛区省一,昨天特别高兴,今天有点高兴,后续会继续更新动态规划的部分;国赛最近也在刷题但有点懒得写博客了,事情有点多。

-----------------2022.04.29--------------------------------

蓝桥杯开始啦

还有七分钟就到九点了,心情有点激动,复习不进去,发个博客吧。

-------------------2022.04.09 7:54-------------------------

目前我做出来的答案,不保真,后期会更新正确答案(如果我能知道的话),同时也欢迎大家一起更正。

1.裁纸刀(5分)

 这个题没有解题思路,但是考虑了三种情况:全横着切、全竖着切、横一刀竖一刀(横着切还是竖着切取决于哪一刀切的长)。发现结果一样,都是443.

2.寻找整数(5分)

 这个题我没做出来,跑不出来。但是群里有人猜是2022040920220409,正好十六位,对方验证答案是对的。多说一句,往年也有这种题,答案和日期相关,但是我第一次参加,没有这种蒙题经验,下次一定试试。

3.质因数个数 时间限制: 10.0s 内存限制: 512.0MB (10分)

思路:先找出n所有的约数,再判断这个约数是否为质数。 

代码测试结果:我试了一个999999998大概只跑了三四秒;试了一个561876588= 2*2*3*3*3* 7*13*17*57*59大概跑了十几秒。所以10^9有一定的通过率,但是不能完全通过。

n=eval(input())
ls=[]
t=0

def isz(x):   #判断是否为质数
    if x%2==0:
        return False
    else:
        for i in range(3,x//2+1,2):
            if x%i==0:
                return False
        return True

for i in range(5,n//2+1,2):  #判断是否为约数
    if n%i==0:
        ls.append(i)
for i in ls:
    if isz(i):
        t+=1

if n%2==0:
    if n%3==0:
        print(t+2)
    else:
        print(t+1)
elif n%3==0:
    print(t+1)
else:
    print(t)

 4. 矩形拼接 时间限制: 1.0s 内存限制: 512.0MB 本题总分:10 分

 

 思路:首先,这个题的答案只有三个可能:4、6、8。

为了先拿到这个10%,我先判断了一下a1=a2=a3.

然后判断4:三个矩形中,各存在一条边xi(i=1,2,3) ,使得x1=x2=x3;或者三个矩形中存在两个矩形1,2,各存在一条边相等x1=x2,这两个矩形的另外一条边相加y1+y2和=最后一个矩形的其中一条边x3(y3)。

判断6:三个矩形中存在两个矩形1,2,各存在一条边相等x1=x2,这两个矩形的另外一条边相加y1+y2和!=最后一个矩形的其中一条边x3(y3)。

判断8:剩下的情况。

这个光代码就写了好久,除了题目案例无测试。

def xiangdeng1(l1,l2,l3):
    flag=0
    for i in l1:
        for j in l2:
            for k in l3:
                if i==j:
                    if j==k:
                        return 2
                    else:
                        for q in l3:
                            if sum(l1)-i+sum(l2)-j==q:
                                return 2
                        flag=1
                elif i==k:
                    for q in l2:
                        if sum(l1)-i+sum(l3)-k==q:
                            return 2
                    flag=1
                elif j==k:
                    for q in l1:
                        if sum(l2)-j+sum(l3)-k==q:
                            return 2
                    flag=1
    if flag:
        return 3
    else:
        return 0

def xiangdeng2(l1,l2,l3):
    for i in l1:
        for j in l2:
            for k in l3:
                if i+j==k or i+k==j or j+k==i:
                    return 6
    return 8
                
    
T=eval(input())
res=[]
for i in range(T):
    s=input().split()
    a1,b1,a2,b2,a3,b3=map(int,s)
    ls=[a1,b1,a2,b2,a3,b3]
    l1=[a1,b1]
    l2=[a2,b2]
    l3=[a3,b3]
    S=a1*b1+a2*b2+a3*b3
    if a1==a2 and a2==a3:
        res.append(4)
    elif 0 not in [S%x for x in ls]:
        res.append(8)
    elif xiangdeng1(l1,l2,l3)!=0:
        res.append(xiangdeng1(l1,l2,l3)*2)
    else:
        res.append(xiangdeng2(l1,l2,l3))

for i in range(T):
    print(res[i])

5.消除游戏 时间限制: 3.0s 内存限制: 512.0MB 本题总分:15 分

思路:先审题,一定是有重复的字符(2个及以上)和不一致的字符才需要删除。

第一步:判断结束:全是一样的或者全是不重复的(不重复表示两个连续的字符不重复,aba这样的重复是可以的)。

删除:我用的是连续的三个字符判断,如果有abb或者aab的情况就删。删除使用的是判断,不能直接删,直接删影响索引。

代码测试:超级快,感觉一秒就出结果了,不知道是不是我的测试用例有问题。

def isok(s):
    if len(s)<=2:
        return False
    else:
        f=1  #判断是否全相等1
        g=1 #判断是否全不想等1
        for i in range(len(s)-1):
            a,b=s[i],s[i+1]
            if ord(a)-ord(b)==0:
                g=0
            else:
                f=0
        if g or f:
            return False
        else:
            return True
        
s=input()
while(isok(s)):
    ls=[1 for i in s]
    for i in range(len(s)-2):
        a,b,c=s[i],s[i+1],s[i+2]
        if a==b and b!=c:
            ls[i+1],ls[i+2]=0,0
        if a!=b and b==c:
            ls[i],ls[i+1]=0,0
    t=''
    for i in range(len(s)):
        if ls[i]==1:
            t+=s[i]
    s=t
if s=='':
    print('EMPTY')
else:
    print(s)

6.重新排序 时间限制: 1.0s 内存限制: 512.0MB 本题总分:15 分

 

 思路:先把每个位置取数的次数求出来,然后把次数和数字的数列分别排序一下,然后两两相乘即得查询结果总和的最大值。减掉原值即可。

这个不好测试,需要的数字太多了。但是我觉得这个思路应该已经很简单了。

n=eval(input())
s=input().split()
A=list(map(int,s))
m=eval(input())
od=[0 for i in range(n)] #保存次数

sum_y=0
sum_x=0
for i in range(m):
    a,b=map(int,input().split())
    for i in range(a-1,b):
        sum_y+=A[i]
        od[i]+=1

A.sort()
od.sort()
for i in range(n):
    sum_x+=A[i]*od[i]
print(sum_x-sum_y)

7.试题 G: 全排列的价值 时间限制: 1.0s 内存限制: 512.0MB 本题总分:20 分

 

 思路:(半猜半对吧)解题角度:每个数字前面的比它小的数字出现的次数。

解释一下图片:因为1是最小的数字,所以1前面出现比它还小的数字的次数为0;

2:比2小的只有1,然后在3!次排序中,1在2前面的可能性为1/2,所以次数就是1/2*3!;

3:比2小的有1,2(2个数字),在3!次排序中,可能性1/2*2,次数就是2/2*3!。

代码测试:例题n=2022答案不到一秒就出来了,估计可以全通过吧。

 

n=eval(input())
res=1
for i in range(1,n+1):
    res*=i
print((res*n*(n-1)//4)%998244353)

8. 试题 H: 最长不下降子序列 时间限制: 1.0s 内存限制: 512.0MB 本题总分:20 分

 

 

考场上没做出来。 

其实在省赛之前我就简单的学了一下动态规划的,但是考试的时候压根没想起来这个题可以用dp,非常伤心,学的还不牢固。所以我又复习了一下,给出我的思路。目前我有两种思路,但是感觉时间复杂度都不低(dp时间复杂度本身也不低)。

【dp需要一定的基础,求固定数列的数列的最长不下降序列的思路我没有写,可以参考其他的博客,因为求单调序列是非常经典的dp,所以介绍的博客非常多,如果找不到可以参考我的动态规划的博客】

1.分段法:思路参考了这个博客,但是做法没有用那个权值线段树(我不会,看起来也颇为复杂)。2022年蓝桥杯省赛 C/C++ A组题解_傅志凌的博客-CSDN博客

 2.遍历法:先把K个数字“拿出来”,然后求剩下的数列的最长不下降序列(dp),取最大值+K即为答案。

这两种方法的时间复杂度都颇高,大概是O(n^3),但是我没找到更简单的算法,但是好像dp有优化的空间,待我学习一下再补充。

#思路1:分段法
def dpxn(ls):   #求以ls[-1]为结尾 的最长不下降序列 的长度----常规代码
    if ls==[]:
        return 0
    n=len(ls)
    dp=[1 for i in range(n)]
    for i in range(n):
        for j in range(0,i):
            if ls[i]>=ls[j]:
                dp[i]=max(dp[i],dp[j]+1)
    return dp[-1]

def dpx0(ls,x0):    #求以x0为开头的 最长不下降序列 的长度----略作修改
    if ls==[]:
        return 0
    n=len(ls)
    dp=[]
    for i in ls:
        if i>=x0:
            dp.append(1)
        else:
            dp.append(0)
    for i in range(n):
        for j in range(0,i):
            if ls[i]>=ls[j] and ls[j]>=x0:
                dp[i]=max(dp[i],dp[j]+1)
    return max(dp)

n,k=map(int,input().split())
ls=list(map(int,input().split()))
res=[]
for i in range(n):
    if i+k<n:
        x0=min(ls[i],ls[i+k])
        res.append(dpxn(ls[:i])+k+dpx0(ls[i+k:],x0))
    else:
        x0=ls[i]
        res.append(dpxn(ls[:i])+n-i-k+1)
print(max(res))
#思路2:遍历法
#===按道理说两种思路在时间复杂度相同的情况下应该会选择更简单的做法,但是我没有找到有类似思路2的做法===
def dpx(ls):   #常规dp代码
    if ls==[]:
        return 0
    n=len(ls)
    dp=[1 for i in range(n)]
    for i in range(n):
        for j in range(0,i):
            if ls[i]>=ls[j]:
                dp[i]=max(dp[i],dp[j]+1)
    return max(dp)

n,k=map(int,input().split())
ls=list(map(int,input().split()))
res=[]
for i in range(n-k):
    l1=ls[:i]
    l2=ls[i+k:]
    l1.extend(l2)
    res.append(dpx(l1))
print(max(res)+k)
#print(res)

我在这个蓝桥杯的训练系统上找到题目了,果然就是说时间超额了【烦】。有做对的大佬捞捞。

9.试题 I: 最优清零方案 时间限制: 5.0s 内存限制: 512.0MB 本题总分:25 分

 

没思路。 

 10.试题 J: 数的拆分 时间限制: 5.0s 内存限制: 512.0MB 本题总分:25 分

 

 

 本质上也没有思路,但是这个题可以用笨办法,于是我就用了笨办法。

import math
n=eval(input())

res=[]
ls=[]
for i in range(n):
    ls.append(eval(input()))

m=max(ls)
lt=[1]
for i in range(2,int(m**0.5)+1):
    for j in range(2,int(math.log(m,i))+1):
        lt.append(i**j)
for i in ls:
    for j in lt:
        if i%j==0 and i//j in lt:
            res.append('yes')
            break
        if i<j:
            res.append('no')
            break
    else:
        res.append('no')

for i in res:
    print(i)
  • 16
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值