链接: A - Legendary Players
def solve():
s, = RS()
p = {'tourist': 3858,
'ksun48': 3679,
'Benq': 3658,
'Um_nik': 3648,
'apiad': 3638,
'Stonefeang': 3630,
'ecnerwala': 3613,
'mnbvmar': 3555,
'newbiedmy': 3516,
'semiexp': 3481,
}
print(p[s])
链接: B - Measure
按题意模拟
PROBLEM = """给定一个正整数N。打印一个长度为(N+1)的字符串,定义如下。
对于每个i=0,1,2,…,N,
如果存在一个在1和9之间的N的因子j,并且i是N/j的倍数,则si是对应最小的j的数字(si将是1,2,...,9中的一个);
如果不存在这样的j,则si为-。
"""
# ms
def solve():
n, = RI()
ans = []
for i in range(n+1):
for j in range(1,10):
if n%j == 0 and i%(n//j) == 0:
ans.append(str(j))
break
else:
ans.append('-')
print(''.join(ans))
链接: C - False Hope
PROBLEM = """有一个3×3的方格,每个方格内写着介于1和9之间(包括1和9)的数字。第i行从顶部开始,第j列从左边开始(1≤i≤3,1≤j≤3)的方格包含数字ci,j。
同一个数字可能写在不同的方格中,但不能在垂直、水平或对角线方向上连续出现三个方格。更确切地说,保证ci,j满足以下所有条件。
对于任意1≤i≤3,不满足ci,1=ci,2=ci,3。
对于任意1≤j≤3,不满足c1,j=c2,j=c3,j。
不满足c1,1=c2,2=c3,3。
不满足c3,1=c2,2=c1,3。
高桥将以随机顺序看到每个方格中的数字。当存在一条线(垂直、水平或对角线),满足以下条件时,他会感到失望。
他看到的前两个方格包含相同的数字,但最后一个方格包含不同的数字。
计算高桥在没有失望的情况下看到所有方格中数字的概率。
约束条件
ci,j∈{1,2,3,4,5,6,7,8,9} (1≤i≤3,1≤j≤3)
对于任意1≤i≤3,不满足ci,1=ci,2=ci,3。
对于任意1≤j≤3,不满足c1,j=c2,j=c3,j。
不满足c1,1=c2,2=c3,3。
不满足c3,1=c2,2=c1,3。
"""
"""听木木老师的:枚举9个数的排列 只有362880种,然后这9个数的排列中,不能有前两个数相同的行是按aab顺序排列的
用bad储存所有这种的线:包括三行三列、两条对角线,每条线最多只有两种方法进bad,因此bad最多只有16个元素(case2就是这种数据)
所以,总复杂度是362880*9*16=52254720
"""
# 527 ms
def solve():
g = []
for _ in range(3):
g.append(RILST())
bad = [] # 失望顺序
for x, y, z in (0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6):
for x, y, z in permutations((x, y, z)):
if g[x // 3][x % 3] == g[y // 3][y % 3]:
bad.append((x, y, z))
# print(bad)
# print(len(bad))
p = 0 # 会失望的排列方法
for q in permutations(range(9)):
for x, y, z in bad:
if q.index(x) < q.index(y) < q.index(z): # 不能有这个顺序,有就寄
p += 1
break
print(1 - p / perm(9))
链接: D - Minimum Width
PROBLEM = """问题陈述
Takahashi在一个窗口中显示了一个有N个单词的句子。所有单词的高度相同,第i个单词(1≤i≤N)的宽度为Li。
这些单词在窗口中以一个宽度为1的空格分隔开。更具体地说,当句子在宽度为W的窗口中显示时,满足以下条件。
句子被分成几行。
第一个单词显示在顶行的开头。
第i个单词(2≤i≤N)要么在第(i-1)个单词之后有一个宽度为1的间隙,要么显示在包含第(i-1)个单词的行的下一行的开头。它不会在其他地方显示。
每行的宽度不超过W。这里,一行的宽度是指从最左边的单词的左端到最右边的单词的右端的距离。
当Takahashi将句子显示在窗口中时,句子适合M行或更少。找出窗口的最小可能宽度。
"""
def lower_bound(lo: int, hi: int, key):
"""由于3.10才能用key参数,因此自己实现一个。
:param lo: 二分的左边界(闭区间)
:param hi: 二分的右边界(闭区间)
:param key: key(mid)判断当前枚举的mid是否应该划分到右半部分。
:return: 右半部分第一个位置。若不存在True则返回hi+1。
虽然实现是开区间写法,但为了思考简单,接口以[左闭,右闭]方式放出。
"""
lo -= 1 # 开区间(lo,hi)
hi += 1
while lo + 1 < hi: # 区间不为空
mid = (lo + hi) >> 1 # py不担心溢出,实测py自己不会优化除2,手动写右移
if key(mid): # is_right则右边界向里移动,目标区间剩余(lo,mid)
hi = mid
else: # is_left则左边界向里移动,剩余(mid,hi)
lo = mid
return hi
# ms
def solve():
n, m = RI()
a = RILST()
def ok(x):
p = 0
c = 1
for v in a:
if p == 0:
p += v
else:
p += v + 1
if p > x:
c += 1
p = v
if c > m:
return False
return True
print(lower_bound(max(a), sum(a) + n - 1, ok))
链接: E - Bus Stops
# 482 ms
def solve():
n, x, y = RI()
pt = []
ll = 1
for _ in range(n - 1):
pt.append(RILST())
ll = lcm(ll, pt[-1][0])
f = [0] * ll # f[i][j]到0时间模ll为j时,从0到达i的时间
for p, t in pt:
for j in range(ll):
f[j] = f[j] + t + (p - f[j] - j) % p # 到达上一步的实际是时间是f[j]+j,那么要等待(p - f[j] - j) % p
q, = RI()
for _ in range(q):
qi, = RI()
print(qi + x + f[(qi + x) % ll] + y) # 到达0的时间是qi+x
# 1178 ms
def solve1():
n, x, y = RI()
pt = []
ll = 1
for _ in range(n - 1):
pt.append(RILST())
ll = lcm(ll, pt[-1][0])
f = [[0] * ll for _ in range(n)] # f[i][j]到0时间模ll为j时,从0到达i的时间
for i, (p, t) in enumerate(pt, start=1):
for j in range(ll):
f[i][j] = f[i - 1][j] + t + (p - f[i - 1][j] - j) % p
q, = RI()
for _ in range(q):
qi, = RI()
print(qi + x + f[-1][(qi + x) % ll] + y)
链接: F - Fighter Takahashi
PROBLEM = """有一棵具有N个顶点的树。第一个顶点是根节点,第i个顶点(2≤i≤N)的父节点是pi(1≤pi
"""由于吃药是乘一个>=1的数,因此一定放在加法后边更好,越滞后越好。
因此优先打怪,用小顶堆优先打弱的怪。打不过了再去吃药。
每次吃药枚举最小的但满足打赢怪的组合。可以直接暴力枚举
"""
# ms
def solve():
n, = RI()
pw = 1 # 初始力量
g = [[] for _ in range(n)]
ee = [(1, 0, 0)] # 根视为100
for i in range(1, n):
p, t, s, gg = RI()
g[p - 1].append(i)
ee.append((t, s, gg))
yao = [] # 现在可用的药
def viagra(pw, t): # 从现在能访问的药里,找到最小的组合,使pw*s>=t,直接状压枚举
if not yao:
return 0
ans = mn = inf # 组合、最小乘积
n = len(yao)
for i in range(1, 1 << n): # 状压
s = 1 # 这个组合的乘积
for j in range(n):
if i >> j & 1:
s *= yao[j]
if s > mn: # 超过当前了不用看了
break
if s * pw >= t and s < mn: # 能打过怪了
mn = s
ans = i
if ans == inf: # 没有能打过怪的组合,直接死
return 0
for j in range(n - 1, -1, -1): # 用掉这些药,逆序
if ans >> j & 1:
yao.pop(j)
return mn
h = [(0, 0)] # 小顶堆,优先搞最弱的怪,如果搞不动,才去吃药,每次吃(最小但满足的组合)
while h:
t, u = heappop(h)
if ee[u][0] == 2:
yao.append(ee[u][2])
if pw < t: # 需要吃药
pw *= viagra(pw, t) # 吃
if pw < t: # 吃完药还是打不过
return print('No')
if ee[u][0] == 1:
pw += ee[u][2]
for v in g[u]:
heappush(h, (ee[v][1], v)) # 如果是药,优先加入药袋,正好它的s是0
print('Yes')