第三届大学生算法大赛(通过率14~20%部分)

D题 投票获胜(通过率14.59%)

题目描述:

解题思路:

  1. 读取输入

    • 第一行输入一个整数 T,表示测试样例的数量。

    • 接下来的 T 行,每行输入一个字符串,只包括字符 'A' 和 'B'

  2. 模拟投票过程

    • 使用一个函数 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,并继续下一轮投票,直到字符串中只剩下一个字符。

  3. 输出结果

                对于每个测试用例,输出一个字符串 "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%)

题目描述:

解题思路:

  1. 理解题目

    • 需要计算三个密钥 XYZ 对应的真实密码。

    • 真实密码是所有小于等于 X 的数 x、所有小于等于 Y 的数 y 和所有小于等于 Z 的数 z 的乘积的和除以 998244353 的余数。

    • 公式为:

  2. 简化计算

    • 直接计算上述公式的时间复杂度非常高,难以在给定的时间限制内完成计算。

    • 我们可以利用数学知识简化计算过程。注意到求和的每一项 xyz 实际上是对三个数的乘积求和。

    • 对于 X,所有小于等于 X 的数的和可以用高斯求和公式计算:\frac{(X+1)X}{2}

    • 同理,对于 Y 和 Z 也可以用同样的方法计算其和。

    • 因此,真实密码可以简化为三个求和结果的乘积再对 998244353 取模。

解题思路详解:

  1. 读取输入

    • 输入三个整数 XYZ,分别表示三个密钥。
  2. 计算求和

    • 使用高斯求和公式计算 XYZ 对应的求和结果:

      • 对于 X\frac{(X+1)*X}{2}

      • 对于 Y\frac{(Y+1)Y}{2}

      • 对于 Z\frac{(Z+1)Z}{2}

    • 注意每次计算求和结果后都要对 998244353 取模。

  3. 计算真实密码

    • 计算三个求和结果的乘积,并再次对 998244353 取模。
  4. 输出结果

    • 输出计算得到的真实密码。

代码实现:

# 读取输入的三个整数 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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值