蓝桥杯python练习题-12

试题A:卡片 本题总分:5分


【问题描述】
小蓝有很多数字卡片,每张卡片上都是数字0到9。
小蓝准备用这些卡片来拼一些数,他想从1开始拼出正整数,每拼一个,就保存起来,卡片就不能用来拼其它数了。
小蓝想知道自己能从1拼到多少。
例如,当小蓝有30张卡片,其中0到9各3张,则小蓝可以拼出1到10,但是拼11时卡片1已经只有一张了,不够拼出11。
现在小蓝手里有О到9的卡片各2021张,共20210张,请问小蓝可以从1拼到多少?
提示:建议使用计算机编程解决问题。

 答案:3181

count=[2021 for i in range(10)]
n=0
flag=0
while True:
    n+=1
    length=len(str(n))
    a=n
    for i in range(length):
        t=a%10#要删除的卡片
        a=a//10
        count[t]-=1
        if count[t]<0:
            flag=1
            break
    if flag:
        break

print(n-1)

 试题B:直线 本题总分:5分


【问题描述】
在平面直角坐标系中,两点可以确定一条直线。如果有多点在一条直线上,那么这些点中任意两点确定的直线是同一条。
给定平面上2×3个整点{(x,y)0 ≤x <2,0≤y <3,x ∈ Z,y ∈Z),即横坐标是О到1(包含0和1)之间的整数、纵坐标是О到2(包含0和2)之间的整数的点。这些点一共确定了11条不同的直线。
给定平面上20×21个整点{(x,y)0 ≤x <20,0 ≤y < 21,x ∈Z,y ∈Z},即横坐标是О到19(包含0和 19)之间的整数、纵坐标是О到20(包含0和20)之间的整数的点。请问这些点一共确定了多少条不同的直线。

答案:40257 

count= []
for i in range(20):#横坐标
    for j in range(21):#纵坐标
        #i,j
        for a in range(i+1,20):
            for c in range(21):
                #a,b
                k=(c-j)/(a-i)
                b=(a*j-c*i)/(a-i)
                count.append((k,b))
count=set(count)
l=len(count)
l=l+20
print(l)

 卡片(附加题)

【问题描述】

小蓝有 k 种卡片, 一个班有 n 位同学, 小蓝给每位同学发了两张卡片, 一 位同学的两张卡片可能是同一种, 也可能是不同种, 两张卡片没有顺序。没有 两位同学的卡片都是一样的。

给定 n, 请问小蓝的卡片至少有多少种?

【输入格式】

输入一行包含一个正整数表示 n 。

【输出格式】

输出一行包含一个整数, 表示答案。

n=int(input())

for k in range(1,n+1):#i种卡片有C(i,2)种分法,再加上i可以和i匹配一种分法
    if k+k*(k-1)//2>=n:
        print(k)
        break

 试题C:货物摆放 本题总分:10分


【问题描述】
小蓝有一个超大的仓库,可以摆放很多货物。
现在,小蓝有n箱货物要摆放在仓库,每箱货物都是规则的正方体。小蓝规定了长、宽、高三个互相垂直的方向,每箱货物的边都必须严格平行于长、宽、高。
小蓝希望所有的货物最终摆成一个大的长方体。即在长、宽、高的方向上分别堆L、W、H的货物,满足n= LxWx H。
给定n,请问有多少种堆放货物的方案满足要求。
例如,当n = 4时,有以下6种方案: 1×1×4、1×2×2、1x4×1、2×1×2、2 ×2×1、4x1×1。
请问,当n= 2021041820210418(注意有16 位数字)时,总共有多少种方案?
提示:建议使用计算机编程解决问题。

 答案:2430

import math
n=int(input())
m=[]
length=int(math.sqrt(n))+1
for i in range(1,length):#把n的因数筛选出来
    if n%i==0:
        m.append(i)
        m.append(n//i)#如果i是因数,n//i一定也是因数
m=list(set(m))#去重
count=0
for i in m:#暴力循环
    for j in m:
        for k in m:
            if i*j*k==n:
                count+=1
print(count)

 试题D:路径 本题总分:10分


【问题描述】

小蓝学习了最短路径之后特别高兴,他定义了一个特别的图,希望找到图中的最短路径。

小蓝的图由2021个结点组成,依次编号1至2021

对于两个不同的结点a,b,如果a和b的差的绝对值大于21,则两个结点之间没有边相连;如果a和b的差的绝对值小于等于21,则两个点之间有一条长度为a和b的最小公倍数的无向边相连。

例如:结点1和结点23之间没有边相连;结点3和结点24之间有一条无向边,长度为24;结点15和结点25之间有一条无向边,长度为75.

请计算,结点1和结点2021之间的最短路径长度是多少。

 注意:题目是要找从1到2021之间的最短路径,不是从1到2021之间的存在所有路径中的最短路径(如果是这样那么结果是1到2结点之间的路径最短,为2)

答案:10266837

import math
def gcd(a,b):#最大公约数
    if b==0:
        return a
    return gcd(b,a%b)
def lcm(a,b):#a和b的最小公倍数
    return (a*b//gcd(a,b))
n=[0 for i in range(2022)]
for i in range(1,2022):#到2021
    for j in range(i+1,i+22):
        if j>2021:#超出停止循环
            break
        if n[j]==0:
            n[j]=n[i]+lcm(i,j)
        else:
            n[j]=min(n[j],n[i]+lcm(i,j))

print(n[2021])

试题E:回路计数 本题总分:15分


【问题描述】
蓝桥学院由21栋教学楼组成,教学楼编号1到21。对于两栋教学楼α和b,当a和b互质时,a和 b之间有一条走廊直接相连,两个方向皆可通行,否则没有直接连接的走廊。
小蓝现在在第一栋教学楼,他想要访问每栋教学楼正好一次,最终回到第一栋教学楼(即走一条哈密尔顿回路),请问他有多少种不同的访问方案?两个访问方案不同是指存在某个i,小蓝在两个访问方法中访问完教学楼i后访问了不同的教学楼。
提示:建议使用计算机编程解决问题。

答案:881012367360 

好像用的是状压dp法,不太会,以下的其他大佬的解题,当个模板看看

from math import gcd
n = int(input())
m = 1 << n
dp = [[0 for j in range(n)] for i in range(m)]  # dp[i][j]对于状态i,i的二进制表示中为1的位置 表示走过了教学楼j
load = [[False for j in range(n)] for i in range(n)]  # 存储i, j之间是否有路
for i in range(1, n + 1):
    for j in range(1, n + 1):
        if gcd(i, j) == 1:
            load[i - 1][j - 1] = True
dp[1][0] = 1
for i in range(1, m):  # 枚举每一种状态
    for j in range(n):
        if i >> j & 1:  # 判断状态i是否包含第j栋教学楼
            for k in range(n):  # 枚举所有可能从教学楼k走到教学楼j的情况
                if i - (1 << j) >> k & 1 and load[k][j]:  # 判断状态i除去j后是否包含k
                    dp[i][j] += dp[i - (1 << j)][k]
print(sum(dp[m - 1]) - dp[m - 1][0])

试题F:时间显示 本题总分:15分

【问题描述】

小蓝要和朋友合作开发一个时间显示的网站。在服务器上,朋友已经获取了当前的时间,用一个整数表示,值为从1970年1月1日00:00:00到当前时刻经过的毫秒数。

现在,小蓝要在客户端显示出这个时间。小蓝不用显示出年月日,只需要显示出时分秒即可,毫秒也不用显示,直接舍去即可。

给定一个用整数表示的时间,请将这个时间对应的时分秒输出。

【输入格式】

输入一行包含一个整数,表示时间。

【输出格式】

输出时分秒表示的当前时间,格式形如HH:MM:SS,其中H表示时,值为0到23,MM表示分,值为0到59,SS表示秒,值为0到59时、分、秒不足两位时补前导0

n=int(input())

n=n//1000#得到秒数

n=n%(60*60*24)

h=str(n//3600)
if len(h)<2:
    h="0"+h
m=str(n%3600//60)
if len(m)<2:
    m="0"+m
s=str(n%3600%60)
if len(s)<2:
    s="0"+s
print(h+":"+m+":"+s)

 试题G:杨辉三角 本题总分:20分

【问题描述】

下面的图形是著名的杨辉三角形:

如果我们按从上到下、从左到右的顺序把所有数排成一列,可以得到如下数列:

1,1,1,1,2,1,1,3,3,1,1,4,6,4,1,

给定一个正整数N,请你输出数列中第一次出现N是在第几个数?

【输入格式】

输入一个整数N.

【输出格式】

输出一个整数代表答案。

 思路:杨辉三角第i行第j列的值为C(i,j),每一列上最先出现的元素都符合C(2k,k)条件,且后面的数一定大于前面的数。注:k为任意常数。本题中的数据最大为10^9,C(32,16)已经大于10^9,所以下面的代码中我们只需要枚举0—16即可。(不是很会)参考大佬:2021年软件类第十二届蓝桥杯 省赛 python组 F-J题解-阿里云开发者社区 (aliyun.com)

n = int(input())
import math
# 求组合数
def C(a, b):
    # return math.comb(a,b) # 可以调用数学库,直接计算
    res = 1
    i = a
    j = 1
    while j <= b:
        res = res * i // j # 分子是b的阶乘,b!
        if res > n: # 组合数是递增的,这时候已经比他大了,直接返回便可
            return res
        i -= 1
        j += 1
    return res

# 二分查找n,由于数字在1000w之内,所以确立一个上界为16
for k in range(16, -1, -1):
    l = 2 * k # 每一个斜边的上的数 L = 2*x
    r = max(n, l)
    res = -1
    # 二分法寻找
    while l <= r:
        mid = l + r >> 1
        if C(mid, k) >= n: # 如果C(mid,k) >= n
            res = mid
            r = mid - 1
        else:
            l = mid + 1
    if C(res, k) == n: # 这时候已经找到我们的行数res,和在第k个
        print((res + 1) * res // 2 + k + 1)
        break
  • 9
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值