Python蓝桥31天,第六天

1. 巧排扑克牌

题目描述

在这里插入图片描述

思路

本质就是约瑟夫循环,就是初始位置为1(root)步长为2的约瑟夫循环

代码

class Node:
    def __init__(self, index, value=None, next=None):
        self.index = index
        self.value = value
        self.next = next


def creatLink(n=13):
    root = Node(1)
    temp = root
    for i in range(2, n + 1):
        temp.next = Node(i)
        temp = temp.next
    temp.next = root
    return root


def show(root):
    temp = root
    while temp.next != root:
        print(temp.index)
        temp = temp.next
    print(temp.index)


if __name__ == '__main__':
    root = creatLink()
    # show(root)
    tem = root
    note = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
    list = [0 for i in range(14)]
    while tem.next != tem:
        list[tem.next.index] = note.pop(0)
        tem.next = tem.next.next
        tem = tem.next
    list[tem.index] = note.pop(0)
    for i in range(1,len(list)):
        if i != len(list)-1:
           print(list[i],end=", ")
        else:
            print(list[i])

2. 质数拆分

题目描述

在这里插入图片描述

思路

01背包问题
Z[] 质数集合
dp[2019] = dp[2019 -Z[1] ] + dp[2019 - Z[2]] +…
dp[2018] = dp[2018 - Z[1]] +…
dp[2017] = dp[2017 - Z[1]] +…

dp[2] = dp[2 - Z[1]] = dp[0] = 1

代码

def isprime(n):
    if n == 2 or n == 3:
        return True
    elif n % 6 != 1 and n % 6 != 5:
        return False
    for i in range(5, int(n ** 0.5) + 2, 6):
        if n % i == 0 or n % (i + 2) == 0:
            return False
    return True

# 将2019以内的所有质数添加进去
res = []
for i in range(2, 2018):
    if isprime(i):
        res.append(i)

dp = [0 for i in range(2020)]
dp[0] = 1
for i in range(len(res)):
    for j in range(2019, res[i] - 1, -1):
        dp[j] += dp[j - res[i]]
print(dp[2019])

3. 日志统计

题目描述

在这里插入图片描述

思路

涉及到两个排序,一个是id一个是ts,我自己写的方法(已经附上)会有一种情况错误,把那一部分换成二分查找竟然就可以了,我也不太清楚为什么。
首先按照id排序,然后再排这个id的ts,查看ts做差,>= d的不要,一个个遍历找ts的范围

代码

import bisect

n,d,k = map(int,input().split()) # n行,d时间,k个赞
dariy = {}
for n in range(n):
    ts,id = map(int,input().split())
    if not dariy.__contains__(id):
        dariy[id] = [ts]
    else:
        dariy[id].append(ts)
keys = sorted(dariy.keys())
for one in keys:
    if len(dariy[one]) >= k:
        dariy[one] = sorted(dariy[one])
        # for i in range(k-1,len(dariy[one])):
        #     if dariy[one][i] - dariy[one][i - k - 1] < d:
        #         print(one)
        #         break
        for i in range(len(dariy[one])):
            td = dariy[one][i] + d
            if (bisect.bisect_left(dariy[one],td) - i >=k):
                print(one)
                break

4. 递增三元组

题目描述

在这里插入图片描述

思路

暴力?打咩!
这里用二分法找到比b小的数量和比b打的数量,两者相乘就是在这个b下,允许出现的排列数量

代码

import bisect
import itertools

N = int(input())
a = sorted(list(map(int, input().split())))
b = sorted(list(map(int, input().split())))
c = sorted(list(map(int, input().split())))

cout = 0
# 法一
# for li in itertools.product(a,b,c):
#     if li[2] > li[1] > li[0]:
#         cout+=1
# 法二
for i in range(len(b)):
    x = bisect.bisect_left(a,b[i])
    y = N - bisect.bisect_right(c,b[i])
    cout += x*y
print(cout)

5. 外卖店优先级

题目描述

在这里插入图片描述

思路

思路都在代码里,主要操作都在优先级的增减上,次要操作都在时间的间隔上

代码

# 输入
N, M, T = map(int, input().split())
producer = {}
for i in range(M):
    ts, id = map(int, input().split())
    if not producer.__contains__(id):
        producer[id] = [ts]
    else:
        producer[id].append(ts)


def judge(x):
    prio = 2 # 初始每家店先放一个单子兜底
    lasttime = x[0]
    for i in range(1, len(x)):
        if x[i] > T: # 如果这个单子时刻大于规定时间内,说明后面的也是,直接break
            break
        if x[i] - x[i - 1] <= 1: # 如果这个单子和上个单子时刻相差1或者0,只加优先级
            prio += 2
        else: # 如果这个单子和上个单子时刻相差大于1,在加优先级的时候要先扣除相应的分数,保底为0
            prio = max(0, prio - (x[i] - x[i - 1] - 1))
            prio += 2
        lasttime = x[i] # 记录最后一个单子的时刻
    if prio > 5 and (prio - (T - lasttime)) > 3: # 如果他的优先级大于5并且,最后无论剩下多长时间,只要你的优先级减去剩下的时间(其实就是减优先级)大于3,就依然在优先缓存里
        return True
    return False

# 一家店一家店的判断
count = 0
for i, t in producer.items():
    t.sort()
    if judge(t):
        count += 1
print(count)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值