D题 投票获胜(通过率14.59%)
题目描述:
解题思路:
-
读取输入
-
第一行输入一个整数
T
,表示测试样例的数量。 -
接下来的
T
行,每行输入一个字符串,只包括字符'A'
和'B'
。
-
-
模拟投票过程
-
使用一个函数
fun(s)
来模拟投票过程,其中s
是一个只包含'A'
和'B'
的字符串。 -
在每一轮中,统计当前字符串中
'A'
和'B'
的数量,分别用fa
和fb
来表示。 -
当字符串中只剩下一个字符时,返回该字符,即表示该字符代表的班级获胜。
-
在每轮投票中,遍历字符串,如果遇到
'A'
并且fb
大于0,则fb
减1(表示禁用了一个'B'
的投票权);否则,将'A'
添加到新字符串r
中,并增加fa
。 -
如果遇到
'B'
并且fa
大于0,则fa
减1(表示禁用了一个'A'
的投票权);否则,将'B'
添加到新字符串r
中,并增加fb
。 -
更新字符串
s
为r
,并继续下一轮投票,直到字符串中只剩下一个字符。
-
-
输出结果
对于每个测试用例,输出一个字符串 "A"
或 "B"
,代表哪个班级获得胜利。
代码实现:
# 定义一个函数来模拟投票过程
def fun(s):
# 初始化两个计数器,fa 表示被禁用的 'A' 数量,fb 表示被禁用的 'B' 数量
fa, fb = 0, 0
# 当字符串中只剩下一个字符时停止循环
while len(set(s)) != 1:
# 初始化索引 i 和新的字符串 r
i, l, r = 0, len(s), ''
# 遍历字符串中的每个字符
while i < l:
# 如果当前字符是 'A'
if s[i] == 'A':
# 如果有 'B' 被禁用,则禁用一个 'B' 的投票权
if fb > 0:
fb -= 1
# 否则,将 'A' 添加到新字符串 r 中,并增加 fa
else:
r += s[i]
fa += 1
# 如果当前字符是 'B'
else:
# 如果有 'A' 被禁用,则禁用一个 'A' 的投票权
if fa > 0:
fa -= 1
# 否则,将 'B' 添加到新字符串 r 中,并增加 fb
else:
r += s[i]
fb += 1
# 移动索引 i
i += 1
# 更新字符串 s 为 r,准备下一轮投票
s = r
# 返回字符串中剩下的唯一字符
return s[0]
# 读取测试用例的数量 T
for _ in range(int(input())):
# 对于每个测试用例,读取一个字符串并调用 fun 函数来预测哪个班级获胜
print(fun(input()))
G题 惊天大劫案(通过率17.36%)
题目描述:
解题思路:
-
理解题目:
-
需要计算三个密钥
X
,Y
,Z
对应的真实密码。 -
真实密码是所有小于等于
X
的数x
、所有小于等于Y
的数y
和所有小于等于Z
的数z
的乘积的和除以998244353
的余数。 -
公式为:
-
-
简化计算:
-
直接计算上述公式的时间复杂度非常高,难以在给定的时间限制内完成计算。
-
我们可以利用数学知识简化计算过程。注意到求和的每一项
xyz
实际上是对三个数的乘积求和。 -
对于
X
,所有小于等于X
的数的和可以用高斯求和公式计算:。 -
同理,对于
Y
和Z
也可以用同样的方法计算其和。 -
因此,真实密码可以简化为三个求和结果的乘积再对
998244353
取模。
-
解题思路详解:
-
读取输入:
- 输入三个整数
X
,Y
,Z
,分别表示三个密钥。
- 输入三个整数
-
计算求和:
-
使用高斯求和公式计算
X
,Y
,Z
对应的求和结果:-
对于
X
: -
对于
Y
: -
对于
Z
:
-
-
注意每次计算求和结果后都要对
998244353
取模。
-
-
计算真实密码:
- 计算三个求和结果的乘积,并再次对
998244353
取模。
- 计算三个求和结果的乘积,并再次对
-
输出结果:
- 输出计算得到的真实密码。
代码实现:
# 读取输入的三个整数 X, Y, Z
x, y, z = map(int, input().split())
# 设置模数
m = 998244353
# 计算 X 的求和结果,并对 m 取模
x1 = ((x + 1) * x // 2) % m
# 计算 Y 的求和结果,并对 m 取模
y1 = ((y + 1) * y // 2) % m
# 计算 Z 的求和结果,并对 m 取模
z1 = ((z + 1) * z // 2) % m
# 计算三个求和结果的乘积,并对 m 取模
p = (x1 * y1 * z1) % m
# 输出真实密码
print(p)
H 极限逃离(通过率14.25%)
题目描述:
理解题目:
- 你有
n
个根据地,从第一个根据地开始逃离,每个相邻根据地之间的距离依次为 1, 2, 3, ...,n-1
。 - 你有
n
个玄学物质,能量分别为 1, 2, ...,n
。 - 每次可以使用一个玄学物质瞬移不超过该物质能量的距离,并且需要在根据地中停留以等待冷却。
- 问题是:逃离成功至少需要使用多少个玄学物质?
解题思路:
- 问题实质上是要找到最少的瞬移次数,使得总距离大于等于
(n-1) * n / 2
(这是从第一个根据地到第n
个根据地的总距离)。 - 瞬移次数
i
与总距离的关系可以通过求和公式来表达:i * (i + 1) / 2
。 - 需要找到满足
i * (i + 1) / 2 >= (n-1) * n / 2
的最小的i
。 - 解决这个问题的一种方法是通过求解二次方程或使用近似的方法找到合适的
i
。
代码实现:
# 读取输入的整数 n,表示根据地的数量和玄学物质的数量。
n = int(input())
# 计算瞬移次数 i 的初步估计值。这里使用了公式 i ≈ sqrt((n - 1) * 2),并通过向下取整得到整数值。
# 该公式来自于求解 i * (i + 1) / 2 ≈ (n - 1) * n / 2 的近似解。
i = int(((n - 1) * 2) ** 0.5)
# 如果当前的 i 满足 i * (i + 1) > (n - 1) * 2,则说明 i 已经足够大,不需要再减小。
# 否则,需要将 i 减小 1,以便更精确地逼近所需的瞬移次数。
if i * (i + 1) > (n - 1) * 2:
i -= 1
# 输出结果:总共需要使用的玄学物质数量为 n - i。
# 这是因为 i 是所需的最小瞬移次数,而我们有 n 个玄学物质,所以剩余未使用的玄学物质数量就是 n - i。
print(n - i)