第十二届蓝桥杯简单题记录

A

# 法一:预设可排列数字范围,循环找1
cnt = 0
for i in range(1,10000):    # 假设可以排列的数字从1到9999
    for j in str(i):
        if int(j) == 1:    # 从1开始排,所以1最先用完
            cnt += 1
            if cnt == 2021:
                print(i)    # 3181
                break

# 法二:while
'''
用str.count()方法统计字符串中某个字符出现的次数
'''
count = 0  # 计数器
i = 1  # 可以排列的数字
while True:  # 循环次数未知,用while循环
    count += str(i).count("1")  # .count("1")方法:统计i中"1"出现的次数
    if count >= 2021:  # 如果"1"出现2021次,说明这次循环中卡片1刚好用完
        print(i) 
        break
    i += 1

B

"""
两点求线的斜率公式: k = (y1-y2)/(x1-x2)
截距公式: b = (x1*y2-x2*y1)/(x1-x2)
"""
points = []   # 存坐标
kbs = []    # 存斜率和截距
x = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]
y = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
# 生成坐标
for i in x:
    for j in y:
        point = (i,j)
        points.append(point)
# 每两点计算斜率和截距
for i in range(len(points)):
    for j in range(i+1, len(points)):
        if points[i][0]-points[j][0] != 0:    # 跳过k=0的线(20条)
            tmp_k = (points[i][1]-points[j][1])/(points[i][0]-points[j][0])
            tmp_b = (points[i][0]*points[j][1]-points[j][0]*points[i][1])/(points[i][0]-points[j][0])    # 注意截距公式
            k_b = (tmp_k,tmp_b)
            kbs.append(k_b)
kb_set = set(kbs)    # 筛选重复值
print(len(kb_set))    # 40237,再加上k=0的20条为答案 40537

"""
学习一下一句话创建坐标
"""
M = [[x, y] for x in range(20) for y in range(21)]  # 创建二维列表:代表xy坐标系

C

'''
不难,但要注意细节和思路,,
'''
num=2021041820210418
ys = {1}
# 找约数
for i in range(1,int(num**0.5)+1):    # 缩小一下范围
    if num % i == 0 :
        tmp_y = num // i
        ys.add(tmp_y)
        ys.add(i)
# 三重for循环找满足题意的数字
cnt = 0
for a in ys:
    for b in ys:
        for c in ys:
            if a*b*c == num:    #条件
                cnt += 1
print(cnt)    # 2430

D

"""
最小公倍数+动态规划。小蓝大佬写得很清楚,这里直接照搬了,学习学习

动态规划的递推公式注意理解:
 dp[i] #i:结点编号1~2021   #dp[i]:当前结点到结点1的最短路径长度
 dp[j] #j:结点编号i+1~i+21 #dp[j]:当前结点到结点i的最短路径长度
此时dp[j]就在比较两个路径的长度,它只选择最短的那条路走:

第一条路:dp[j],代表之前存在dp列表里的最小路径(当前结点到结点1的最小路径)。
第二条路:dp[i]+lcm(i,j),代表假如现在的dp[i]加上新路lcm(i,j),这时候的路径长度。
比较dp[j]和dp[i]+lcm(i,j)哪条路更短,只走近路(min)的dp[j]就跟它走


无穷数:dp=[float('inf')]
"""

#最小公倍数模板(least common multiple)
def lcm(a,b):
    s=a*b
    while b:
        a,b=b,a%b    # 辗转相除,得最大公因数
    return s//a    # 乘积除最大公因数就是最小公倍数
 
#最短路径(dp)
n=2021                          #结点数量
dp=[float('inf')]*(n+1)         #创建n+1个无穷元素的列表
dp[1]=0                         #结点1的长度初始化为0
for i in range(1,n+1):          #结点a:遍历结点1~n
    for j in range(i+1,i+22):   #结点b:遍历结点i+1~i+21
        if j>n:                 #j超出结点范围时
            break               #结束循环
        dp[j]=min(dp[j],dp[i]+lcm(i,j))#递推公式
print(dp[n])                    #输出结果:10266837
 

F

"""
时间模块的函数应用:
time.actime() 将时间元组转换为一个表示人类可读的时间字符串。
time.gmtime() 将该秒数解释为格林尼治标准时间(GMT)的时间元组。
这个时间元组包含了年、月、日、时、分、秒等信息。

n//1000 --> 毫秒和秒的转换,相差1000
print("{:02d}:{:02d}:{:02d}".format(h,m,s))  控制输出两位数字
"""
# 法一
import time
n=int(input())
# 返回提取出其中的第 11 到第 19 个字符,即时间的小时、分钟和秒部分。
#这样就得到了形如 "HH:MM:SS" 的时间格式
print(time.asctime(time.gmtime(n//1000))[11:19])    



# 法二:底层算法方法
n = 1618708103123 
n //= 1000        # ms->s
n %= 24*60*60     #最近1天:4103s
s = n % 60        #23s
n //= 60          #s->min
h = n // 60       #1h
m = n %  60       #8min
# 注意输出格式
print("{:02d}:{:02d}:{:02d}".format(h,m,s)) 

G

思路: 

第十二届蓝桥杯B组C/C++省赛—H题(杨辉三角)_思维题_杨辉三角最大路径题-CSDN博客 

 

枚举顺序

首先对于左半边杨辉三角来说,每行最大的数一定出现在该行末尾,同时它也是该数最早出现的位置
因此我们不妨从第16斜行开始枚举,只要出现等于 n 的数直接返回位置即可
对于查找,我们可以对每个斜行采用二分的方法查找n
对于位置,我们可以在查找的时候确定,n所在行 r(不是斜行)和所在斜行 k ,然后通过等差公式 r*(r+1)/2 计算它之前数目的个数再加上 k+1

"""
小蓝的代码。思路是斜着找,但我没明白斜着的数组的规律
代码里有一些模板可以看看
"""
# 组合值模板
def C(a, b):  
    res = 1
    fz = a #分子
    for fm in range(1,b+1): #1~b
        res = res * fz // fm#递推公式=分子//分母
        fz -= 1
        if res > n:
            return res
    return res
#二分查找
def check(k): #k:斜行
    l, r = 2*k, n   #赋初值left:2k right:n
    while l < r:
        mid = l + r >> 1 # >>1:相当于(l+r)//2
        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())
if n == 1:
    print(1)
else:
    for k in range(16,0,-1):#从16斜行枚举
        if check(k)==True:
            break


# 不是答案的暴力,,构建杨辉三角形,转一维,顺序查找。
yh = []
for i in range(1000):
    for j in range(i+1):
        if i == 0:
            yh.append([1])
            continue
        if j == 0:
            tmp_list = []
            tmp_list.append(1)
        elif j == i:
            tmp_list.append(1)
            yh.append(tmp_list)
        else:
            tmp = yh[i-1][j-1]+yh[i-1][j]
            tmp_list.append(tmp)
yh_one = []
for i in range(len(yh)):
    for j in range(len(yh[i])):
        yh_one.append(yh[i][j])
N = int(input())
for i in range(len(yh_one)):
    if yh_one[i] == N:
        print(i+1)
        break

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值