第十三届蓝桥杯省赛pythonA组

试题B 寻找整数

在这里插入图片描述
很自然的想法就是缩小检索数的范围,观察可发现%11和%17的结果都为0,则数必定为11和17的最小公倍数的倍数,即n=k1117(其中k为自然数),但检索范围还是有点大。

这次我们可以针对k做文章,发现1117%3=1,而11172%3=2,则可以发现1117*(3k+2)都会满足%3=2,又因为%2=1,即n为奇数,因此k要为奇数。于是我们很自然的就想当k为多少时,满足1117(3k+2)%4=1,同理可以不断的进行下去……我们当然希望选取更少的数来判断,因此就需要扩大选取的步长,且最好选取质数(因为非质数有时k会重复)

#找质数的余数之间关系缩小数的范围 这里以%3余2为主体(即3k+2),然后依次循环13,23,37,43,47等缩小k的范围提高运行效率
tmp=[0,0]  #记录缩小的范围(起始数和步长)
i=0
for k in range(1,1000000,2): #因为%2=1,所以不能为2的倍数,因此3k+2,k要为奇数
    if 187*(3*k+2)%13==10:
        tmp[i]=k
        i+=1
        if i==2:
            i=0
            break
for k in range(tmp[0],1000000,tmp[1]-tmp[0]):#根据上一步算出来的结果来调整相应的起始数和步长
    if 187*(3*k+2)%29==16:
        tmp[i]=k
        i+=1
        if i==2:
            i=0
            break
for k in range(tmp[0],10000000,tmp[1]-tmp[0]):
    if 187*(3*k+2)%37==22:
        tmp[i]=k
        i+=1
        if i==2:
            i=0
            break
for k in range(tmp[0],100000000,tmp[1]-tmp[0]):
    if 187*(3*k+2)%41==1:
        tmp[i]=k
        i+=1
        if i==2:
            i=0
            break
for k in range(tmp[0],1000000000,tmp[1]-tmp[0]):
    if 187*(3*k+2)%47==5:
        tmp[i]=k
        i+=1
        if i==2:
            i=0
            break
dp=[187*(3*k+2) for k in range(tmp[0],pow(10,14),tmp[1]-tmp[0])]
dic={2: 1, 3: 2, 4: 1, 5: 4, 6: 5, 7: 4, 8: 1, 9: 2, 10: 9, 11: 0,
     12: 5, 13: 10, 14: 11, 15: 14, 16: 9, 17: 0, 18: 11, 19: 18,
     20: 9, 21: 11, 22: 11, 23: 15, 24: 17, 25: 9, 26: 23, 27: 20,
     28: 25, 29: 16, 30: 29, 31: 27, 32: 25, 33: 11, 34: 17, 35: 4,
     36: 29, 37: 22, 38: 37, 39: 23, 40: 9, 41: 1, 42: 11, 43: 11,
     44: 33, 45: 29, 46: 15, 47: 5, 48: 41, 49: 46}
for n in dp:
    for i in range(2,50):
        if n%i!=dic[i]:
            break
    else:
        print(n)
        break

答案

2022040920220409
试题C

在这里插入图片描述
判断素数

def zhi(n):
    num=0
    for i in range(2,int(n**0.5)+1):
        if(n%i==0):
            return False
    return True

代码:
但是没有平台测评过

import math
def zhi(n):
        num=0
        for i in range(2,int(n**0.5)+1):
            if(n%i==0):
                return False
        return True

n=int(input())
k=0      
for i in range(2,n//2):
    if(zhi(i) and n%i==0):
        k+=1
print(k)
试题D 矩形拼接

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
矩形的拼接一共有3种情况
分别是: 4,6,8
4就是刚好能合起来
6就是有一个小一点,凹进去了
8就是都合不上
**
4:
情况一:三个矩形中 ,各存在一条边xi(i=1,2,3) ,使得x1=x2=x3
情况二:三个矩形中存在两个矩形1,2 ,各存在一条边相等x1=x2,这两个矩形的另外一条边相加y1+y2和=最后一个矩形的其中一条边 x3(y3) 。
**
三个矩形中存在两个矩形1,2,这两个矩形的另外一条边相加y1+y2和=最后一个矩形的其中一条边x3(y3)。

def check4(x1,x2,x3,a):# 有保证一边等于另外两边之和,但是要排除总共是4条边的情况
    if x1==x2+x3 and a[2]+a[3]-x2==a[4]+a[5]-x3:
        return True    #此时只有4条边,因为另外两条边相等
    if x2==x1+x3 and a[0]+a[1]-x1==a[4]+a[5]-x3:
        return True
    if x3== x2+x1 and a[0]+a[1]-x1==a[2]+a[3]-x2:
        return True
    return False
def check6(x1,x2,x3):
    if x1==x2+x3 or x2==x1+x3 or x3==x1+x2:
        return True
    return False
if __name__=='__main__':
    N=int(input())
    for n in range(N):
        edge=8
        a=list(map(int , input().strip().split()))
        for i in range(0,2):
            for j in range(2,4):
                for k in range(4,6):
                    x1,x2,x3=a[i],a[j],a[k]
                    if x1==x2 and x2==x3: #有三条边相等
                        edge=min(edge,4)
                    if check4(x1,x2,x3,a):  #总共有4条边的情况
                        edge=min(edge,4)
                    if x1==x2 or x2==x3 or x1==x3:
                        edge=min(edge,6)
                    if check6(x1,x2,x3):
                        edge=min(edge,6)
        print(edge)
"""
2
2 3 4 1 2 4
1 2 3 4 5 6
"""
试题E 消除游戏(还是模拟解决)

在这里插入图片描述
在这里插入图片描述

思路

一次判断全部的边缘字母,记录下标,然后一次性把所有的字母pop()出去, 再根据新的列表来判断。
以下是只能通过7个测试用例的代码, 还有5个运行超时

n=list(input())    # 把所有的字母单独分析
num=0
while num<2**65:
    clear1=[]      #  记录边缘下标
    l=len(n)
    for i in range(len(n)): 
        if(i-1>=0 and  i+1<len(n)):
            if(n[i-1]==n[i] and n[i]!=n[i+1]):
                clear1.append(i)
                clear1.append(i+1)
            if(n[i-1]!=n[i] and n[i]==n[i+1]):
                clear1.append(i-1)
                clear1.append(i)
    num+=1;
    clear1=list(set(clear1))
    clear1=sorted(clear1, reverse=True)
    for j in clear1:
        n.pop(j)
    if(l==len(n)):
        break;  
if(len(n)==0):
    print("EMPTY")
else:
    for i in range(len(n)):
        print(n[i],end="")  
试题F 重新排序

在这里插入图片描述
(差分的思想)
差分其实就是数据之间的差,什么数据的差呢?就是上面所给的原始数组的相邻元素之间的差值,我们令 d[i]=a[i+1]-a[i],一遍for循环即可将差分数组求出来。
下面给你一个栗子,给出一个差分数组先
在这里插入图片描述
差分数组怎么求
其实差分数组是一个辅助数组,从侧面来表示给定某一数组的变化,一般用来对数组进行区间修改的操作

还是上面那个表里的栗子,我们需要进行以下操作:

1、将区间【1,4】的数值全部加上3

2、将区间【3,5】的数值全部减去5

很简单对吧,你可以进行枚举。但是如果给你的数据量是1e5,操作量1e5,限时1000ms你暴力枚举能莽的过去吗?T到你怀疑人生直接。这时我们就需要使用到差分数组了。

其实当你将原始数组中元素同时加上或者减掉某个数,那么他们的差分数组其实是不会变化的。
利用这个思想,咱们将区间缩小,缩小的例子中的区间 【1,4】吧这是你会发现只有 d[1]和d[5]发生了变化,而d[2],d[3],d[4]却保持着原样。
在这里插入图片描述
发现是头和尾发生了改变,其中区间头+该数字,区间尾-该数字,然后用差分的公式,就能把所有的区间都算出来啦。
a[i]=a[i-1]+d[i]
应用差分的思想,就可以让时间复杂度降低了。

import sys
n= int(input())
a=[0]*1000005
a[1:n+1]=list(map(int,input().split(' ')))
m=int(input())
s=[0]*1000001  # 差分数组
u=[0]*(n+1)
yuan=0
for i in range(m):
    w=input().split()
    s[int(w[0])]+=1
    s[int(w[1])+1]-=1
  
for i in range(1,n+1):
    u[i]=u[i-1]+s[i]
    
for i in range(1,n+1):
    yuan+=a[i]*u[i]
    
u[1:n+1]=sorted(u[1:n+1])
a[1:n+1]=sorted(a[1:n+1])
now=0
for i in range(1,n+1):
    now+=a[i]*u[i]
print(now-yuan)

在这里插入图片描述

试题G: 全排列的价值

问题描述
对于一个排列 A=(a1​,a2​,⋯,an​), 定义价值 ci​ 为 a1​ 至 ai−1​ 中小于 ai​ 的数 的个数, 即 。
ci​=∣{aj​∣j<i,aj​<ai​}∣。 ​
定义 A 的价值为 ∑i=1n​ci​ 。
给定 n, 求 1 至 n 的全排列中所有排列的价值之和。

输入格式
输入一行包含一个整数 n 。

输出格式
输出一行包含一个整数表示答案, 由于所有排列的价值之和可能很大, 请 输出这个数除以 998244353 的余数。
样例输入 1
3

思路:

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值