第十二届蓝桥杯真题 python

A题 空间:

n=256*1024*1024*8//32
print(n)

#1MB=1024KB=1024*1024B=1024*1024*8bit
#32位二进制 为32bit

B题 卡片:

f=[2021 for i in range(10)]
res=1
flag=1
while True:
    c=res
    while c:
        a=c%10
        if f[a]:
            f[a]-=1
        else:
            flag=0 #flag[a]当前数已经构造不出来,所以应该-1
            break
        c//=10
    if flag==0:
        break
    res+=1
print(res-1)
    

C题 直线:

s=[]
#为了区分直线,不能光存斜率,还要存上不同的截距
for x1 in range(20):
    for y1 in range(21):
        for x2 in range(20):
            for y2 in range(21):
                if x1!=x2:
                    k=(y1-y2)/(x1-x2)
                    b=(x2*y1-x1*y2)/(x2-x1)
                    #y-y1=k(x-x1) 截距x=0
                    s.append((k,b))                
s=set(s)
print(len(s)+20)

D题 货物摆放:

n=2021041820210418
s=[]
res=0
for i in range(1,round(n**0.5)):
    if n%i==0:
        s.append(i)
        if i!=n//i:
            s.append(n//i)
#因为i和n/i可能相等,去重
print(len(s))
for i in range(len(s)):
    for j in range(len(s)):
        for k in range(len(s)):
            if s[i]*s[j]*s[k]==n:
                res+=1
print(res)

E. 路径

#a和b的最小公倍数=a*b/a和b的最大公因数
#1.求最小公倍数
#2.最短路:Floyd算法(适合n<300的小图) (无向图)(多源最短路径)
import math

def lcm(a,b):
    if a<b:
        a,b=b,a
    c,d=a,b
    while d!=0:
        c,d=d,c%d
    return (a*b)//c

def gcd(a,b):
    if b==0:
        return a
    else:
        return gcd(b,a%b)
n=2100 #f[i][j] i和j节点之间的最短路径
#分割: 直接有i->j,没有i->j: f[i][j]=min(f[i][j],f[i][k]+f[k][j])
f=[[float('inf') for i in range(n)]for i in range(n)]
f[1][1]=0
for i in range(1,2022): #节点a
    for j in range(i+1,i+22): #结点b abs(b-a)<=21
        if j>2021:
            break
        f[1][j]=min(f[1][j],f[1][i]+i*j//math.gcd(i,j))#法一:调用库函数
        f[1][j]=min(f[1][j],f[1][i]+lcm(i,j))#法二:自己写函数
        f[1][j]=min(f[1][j],f[1][i]+i*j//gcd(i,j))#法三:自己写函数
print(f[1][2021])
n=2021
st=[0 for i in range(2025)]
g=[[float('inf') for i in range(2025)]for i in range(2025)]

def gcd(a,b):
    if b==0:
        return a
    return gcd(b,a%b)

def lcm(a,b):
    return a*b//gcd(a,b)

def add(a,b,c):
    g[a][b]=c
    g[b][a]=c

def dijkstra():
    dist=[float('inf') for i in range(2025)]
    dist[1]=0
    for i in range(n):
        t=-1
        for j in range(1,n+1):
            if (not st[j]) and (t==-1 or dist[t]>dist[j]):
                t=j
        for j in range(1,n+1):
            dist[j]=min(dist[j],dist[t]+g[t][j])
        st[t]=1
    return dist[2021]

for a in range(1,2022):
    for b in range(a+1,2022):
        if b-a<=21:
            c=lcm(a,b)
            add(a,b,c)
            add(b,a,c)
print(dijkstra())
        

E题:回转路径

from math import gcd 
n=1<<21
dp=[[0 for i in range(22)]for j in range(n+1)] #dp[i][j] i状态下,目的地为j的方案数
#划分:访问k教学楼 dp[i+1<<k][k]+=dp[i][j]
g=[[0 for i in range(22)]for i in range(22)] #g[i][j] i与j之间是否有路

for i in range(1,22):
  for j in range(1,22):
    if gcd(i,j)==1:
      g[i-1][j-1]=g[j-1][i-1]=1

dp[1][0]=1
i=1
while i<n:
  for j in range(21):
    if (i>>j&1)==0: #i状态的j教学楼未被访问过
      continue
    for k in range(21):
      if g[j][k]==0 or (i>>k&1)!=0: #i状态k教学楼被访问过,j和k之间没路
        continue
      #j和k之间有路(g[j][k]!=0),且j被访问过和k未被访问过 (i >> k & 1) = 0
      dp[(i+(1<<k))][k]+=dp[i][j]
  i+=1
res=0
for i in range(21):
  res+=dp[n-1][i]
print(res)

#前提条件:i到j访问过,j到k有路,i到K要被访问 方案为i->j->k
#关键公式dp[i+(1<<k)][k]+=dp[i][j]
#i状态下,访问k终点为k,方案数为原状态加上i->j的方案数

#步骤1.建邻接表,判断两个教学楼之间是否有路
#2.利用状压dp开始走
#3.计算方案数

F题:杨辉三角形

#杨辉三角先确定规律 见网址https://www.acwing.com/solution/content/96316/
def C(a,b):#Cab
  #Cab=a!/b!/(a-b)!=a*(a-1)*...*(a-b+1)共b项/b!
  i=a
  j=1
  res=1
  while j<=b:
    res=res*i//j
    i-=1
    j+=1
    if res>n:
      return res
  return res

#Clk~Clr范围
def check(k):
  l=2*k
  r=max(l,n)
  while l<r:
    mid=l+r>>1
    if C(mid,k)>=n:
      r=mid
    else:
      l=mid+1
  if C(r,k)!=n:
    return False
  print(r*(r+1)//2+k+1)
  return True

n=int(input())
for i in range(16,-1,-1):
  if check(i):
    break




[蓝桥杯2019初赛]立方和

N=2019
ssum=0
for i in range(1,N+1):
    a=i
    while a:
        b=a%10
        if b==2 or b==0 or b==1 or b==9:
            ssum+=i*i*i
            break
        a//=10
print(ssum)

[蓝桥杯2019初赛]RSA解密

from math import *
n = 1001733993063167141
k = int(sqrt(n))
for i in range (2,k):
   if(n%i==0):
       p,q=i,n//i
       #print(i,n//i) 求出p,q的值 运行的时候不要质疑代码 是真的慢
#n = 1001733993063167141
d = 212353
#p = 891234941
#q = 1123984201
tmp=(p - 1)*(q - 1)
print(tmp)
#(d*e)%tmp==1, num==d*e
for i in range(2,n+1):
    num = i * tmp + 1
    if(num % d == 0):
        e=num//d
        #print(num // d)
        break
#e=823816093931522017#以上是求e的值
def qpow(a,b,mod):
    ret=1
    while b:
        if(b&1): #二进制位为1
            ret = ret * a% mod
        a=a*a%mod
        b>>=1
    return ret
#这是一个快速幂函数
print(qpow(20190324,e,n))
#按概念做本题
#先求p,q d*e 
n=1001733993063167141
d=212353
C=20190324
i=2
while i<=n**0.5:
    if n%i==0:
        p,q=i,n//i
        print(p)
        print(q)
        break
    i+=1
tmp=(p-1)*(q-1)
print(tmp)
#再求e
for i in range(n+1):
    de=i*tmp+1
    if de%d==0:
        e=de//d
        print(e)
        break

#接下来使用快速幂

def qpow(a,b,mod):
    ssum=1
    while b:
        if b&1:
            ssum=ssum*a%mod
        a=a*a%mod
        b>>=1
    return ssum

print(qpow(C,e,n))
        

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值