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)