看不到代码请重新刷新此页面

以下都是已做过的

链接:

蓝桥杯题库

需要原题或者试题请点击蓝色字体!

确定字符串是否包含唯一字符

题解

这段代码的功能是检查输入的字符串 s 中是否有重复的字符(忽略大小写)。如果没有重复字符,输出 "YES";如果有重复字符,输出 "NO"


代码分析:

  1. 输入处理

    1. s = input():从用户输入获取字符串。

    2. s = s.upper():将字符串 s 中的所有字母转换为大写字母(忽略大小写)。

  1. 检查重复字符

    1. 初始化一个空列表 d,用于存储已经出现过的字符。

    2. 使用 for 循环遍历字符串 s 中的每个字符 i

      • 如果 i 不在列表 d 中,则将 i 添加到 d 中。

      • 如果 i 已经在列表 d 中,说明字符重复,输出 "NO" 并结束循环。

  1. 输出结果

    1. 如果循环正常结束(没有 break),说明字符串中没有重复字符,输出 "YES"


示例运行:

输入 1:

abd25+

输出 1:

YES

解释:

  • 转换后的字符串:"ABD25+"

  • 所有字符都是唯一的,没有重复字符。


输入 2:

hello

输出 2:

NO

解释:

  • 转换后的字符串:"HELLO"

  • 字符 'L' 重复了,因此输出 "NO"


输入 3:

12345

输出 3:

YES

解释:

  • 转换后的字符串:"12345"

  • 所有字符都是唯一的,没有重复字符。


代码改进建议:

  1. 使用集合(**set****)优化**:

    1. 列表 d 的查找操作 if i not in d 的时间复杂度是 \(O(n)\),而集合的查找操作是 \(O(1)\)。

    2. 使用集合可以显著提高代码的效率。

  1. 简化代码

    1. 可以直接比较字符串的长度和集合的长度来判断是否有重复字符。


改进后的代码:

s = input()  # 获取输入字符串
s = s.upper()  # 转换为大写字母

# 使用集合检查是否有重复字符
if len(s) == len(set(s)):
    print("YES")
else:
    print("NO")

改进后的代码分析:

  1. 集合的特性

    1. 集合(set)是一种无序且不重复的数据结构。

    2. 将字符串 s 转换为集合后,重复字符会被自动去重。

  1. 判断逻辑

    1. 如果字符串 s 的长度等于集合的长度,说明没有重复字符。

    2. 否则,说明有重复字符。


示例运行:

输入 1:

abd25+

输出 1:

YES

输入 2:

hello

输出 2:

NO

输入 3:

12345

输出 3:

YES

拼数

答案

n = int(input())
m = input().split()

for i in range(n-1):
    for j in range(i+1,n):
        if m[i]+m[j] < m[j]+m[i]:
            m[i],m[j] = m[j],m[i]
print(''.join(m))

这段代码的目的是将一组字符串表示的**数字拼接成最大的可能数值**。其核心思路是通过**自定义排序规则**,确保最终的拼接结果最大。


代码分步解析

1. 输入处理

n = int(input())          # 输入数字的个数
m = input().split()       # 输入数字,保存为字符串列表
  • 示例输入3"3 30 34"m = ["3", "30", "34"]

2. 双重循环排序逻辑

for i in range(n-1):
    for j in range(i+1, n):
        if m[i] + m[j] < m[j] + m[i]:  # 比较拼接后的字典序
            m[i], m[j] = m[j], m[i]    # 交换位置
  • 核心规则:如果 m[i]m[j] 的当前顺序拼接结果(如 "3"+"30"="330")**小于**交换后的结果("30"+"3"="303"),则交换两者的位置。

  • 排序目标:经过排序后,任意两个元素 m[i]m[j]i < j)满足 m[i] + m[j] >= m[j] + m[i],确保整体拼接结果最大。

3. 输出结果

print(''.join(m))  # 拼接所有元素并输出
  • 示例输出:输入 ["3", "30", "34"] → 输出 "34330"


关键逻辑验证

示例 1:输入 ["3", "30", "34"]

  1. 初始顺序["3", "30", "34"]

  2. 第一轮循环 (**i=0****)**:

    1. 比较 "3"+"30""330")和 "30"+"3""303")→ 不交换。

    2. 比较 "3"+"34""334")和 "34"+"3""343")→ 交换 → ["34", "30", "3"]

  3. 第二轮循环 (**i=1****)**:

    1. 比较 "30"+"3""303")和 "3"+"30""330")→ 交换 → ["34", "3", "30"]

  4. 最终结果"34330"(最大可能值)。

示例 2:输入 ["10", "2"]

  1. 比较 "10"+"2""102")和 "2"+"10""210")→ 交换 → ["2", "10"]

  2. 最终结果"210"(正确)。


时间复杂度分析

  • 当前代码:双重循环的复杂度为 **O(n²)**,适用于 n < 1000 的小数据量。

  • 优化方案(大数据量适用):

    from functools import cmp_to_key
    m.sort(key=cmp_to_key(lambda a, b: -1 if a + b > b + a else 1))  # O(n log n)

代码总结

代码

作用

时间复杂度

适用场景

for i in range(n-1): ...

通过双重循环逐个比较元素

O(n²)

小数据量(n < 1000

m.sort(key=cmp_to_key(...))

使用高效排序优化

O(n log n)

大数据量(n ≥ 10^4

核心目标:确保拼接后的字符串字典序最大。

查找两个总和为特定值的索引

答案

n = int(input())
a = list(map(int,input().split()))
k = int(input())

for i in a:
    if k-i in a:
        print(a.index(i),a.index(k-i))
        break

以下是Ai给的建议

这段代码的目的是在列表 a 中找到两个数,使它们的和等于给定的整数 k,并输出这两个数的索引。让我们详细解析这段代码:

代码解析

  1. 输入部分

    1. n = int(input()):读取一个整数 n,表示列表 a 的长度(但后续并未使用)

    2. a = list(map(int, input().split())):读取一行数字并转换为整数列表

    3. k = int(input()):读取目标整数 k

  1. 查找逻辑

    1. 遍历列表 a 中的每个元素 i

    2. 检查 k - i 是否也在列表 a

    3. 如果找到,则打印这两个数的索引(使用 a.index() 方法)并立即退出循环

  1. 输出部分

    1. 打印找到的两个数的索引

潜在问题

  1. 重复元素问题

    1. a.index() 方法总是返回第一个匹配项的索引

    2. 例如,如果 a = [3, 3]k = 6,代码会输出 (0, 0) 而不是正确的 (0, 1)

  1. 同一元素被使用两次

    1. 如果 k - i == i 且该元素只出现一次,代码会错误地认为找到了解

    2. 例如,a = [3]k = 6,会输出 (0, 0)

  1. 效率问题

    1. a.index() 的时间复杂度是 O(n)

    2. 整个算法的时间复杂度是 O(n²),对于大数据量效率较低

  1. 无解情况

    1. 如果没有解,代码不会有任何输出

改进建议

  1. 使用哈希表优化

    a = list(map(int, input().split()))
    k = int(input())
    seen = {}
    
    for i, num in enumerate(a):
        complement = k - num
        if complement in seen:
            print(seen[complement], i)
            exit()
        seen[num] = i
    
    print("No solution")
  1. 改进点

    1. 时间复杂度从 O(n²) 降到 O(n)

    2. 正确处理重复元素

    3. 明确处理无解情况

    4. 不需要预先知道列表长度 n

示例分析

输入1:

6
1 2 3 -2 5 7
7

输出1:

1 4

解释:2 + 5 = 7,索引分别是1和4

输入2:

3
3 3 3
6

原代码输出:

0 0

改进代码输出:

0 1

输入3:

2
1 2
4

改进代码输出:

No solution

总结

原代码在元素唯一时能正确工作,但存在重复元素时会出错。改进方案使用哈希表存储已遍历元素,既提高了效率,又解决了重复元素的问题。

小蓝爱串串

n,m = map(int,input().split())
a = sorted(input()for i in range(n))
print(''.join(a))

这段代码的功能是读取 n 个字符串,将它们按字典序排序后拼接成一个字符串输出。让我们详细解析:

代码解析

  1. 输入部分

    1. n, m = map(int, input().split()):读取两个整数 nm(虽然 m 在后续代码中并未使用)

    2. a = sorted(input() for i in range(n)):读取 n 个字符串并立即进行排序

  1. 处理部分

    1. sorted() 函数对输入的字符串进行字典序排序

    2. 排序结果存储在列表 a

  1. 输出部分

    1. print(''.join(a)):将排序后的字符串列表拼接成一个字符串输出

示例运行

输入1:

3 5
apple
banana
cherry

输出1:

applebananacherry

解释:按字典序排序后拼接

输入2:

4 3
cat
bat
mat
hat

输出2:

batcathatmat

注意事项

  1. 变量 m** 未使用**:代码中读取了 m 但后续没有使用,可能是为了符合某些题目输入格式要求

  2. 排序规则:使用 Python 默认的字典序排序(基于 Unicode 码点)

  3. 拼接方式:直接使用 ''.join() 无间隔拼接

改进建议

如果题目有特殊要求(如字符串长度固定为 m),可以添加验证:

n, m = map(int, input().split())
a = [input().strip() for _ in range(n)]
assert all(len(s) == m for s in a), "所有字符串长度必须为"+str(m)
print(''.join(sorted(a)))

时间复杂度

  • 排序:O(n log n)(Python 的 Timsort 算法)

  • 空间复杂度:O(n)(存储所有字符串)

这段代码简洁高效,适用于需要将多个字符串按字典序合并的场景。

串串匹配

答案

from collections import Counter
n,m=map(int,input().split())
a = [input().strip() for _ in range(n)]
b=[''.join(sorted(_)) for _ in a]
c =Counter(b)
count = 0
for k,v in c.items():
    count += v*(v-1)//2
print(count)

这段代码用于统计互为字母异位词(Anagram)的字符串对数量。其核心思路是通过字符排序标准化字符串,然后统计每组字母异位词的组合数。以下是详细解析:


代码功能

统计所有互为字母异位词的字符串对数目。

字母异位词:两个字符串字符组成相同但顺序不同(如 "listen""silent")。


代码步骤解析

  1. 输入处理

    n, m = map(int, input().split())      # 读取字符串数量 n 和长度 m
    a = [input().strip() for _ in range(n)]  # 读取 n 个字符串
  1. 标准化处理

    b = [''.join(sorted(_)) for _ in a]   # 对每个字符串的字符排序(标准化)
    • 例如:"bac" → "abc""silent" → "eilnst"

    • 目的:互为字母异位词的字符串标准化后形式相同。

  1. 统计标准化字符串出现次数

    c = Counter(b)  # 统计每个标准化字符串的出现次数
    • 示例:输入 ["ab", "ba", "ca"] → 标准化后 ["ab", "ab", "ac"]Counter({'ab': 2, 'ac': 1})

  1. 计算满足条件的字符串对数目

    count = 0
    for k, v in c.items():
        count += v * (v - 1) // 2  # 组合数 C(v,2)
    print(count)
    • 组合数公式:从 v 个相同标准化字符串中选 2 个的组合数 \( C(v,2) = \frac{v(v-1)}{2} \)。

    • 例如:某组有 3 个字母异位词,可组成 \( 3 \times 2 / 2 = 3 \) 对。


关键逻辑验证

输入 1

3 2
ab
ba
ca
  • 标准化结果["ab", "ab", "ac"]Counter({'ab': 2, 'ac': 1})

  • 计算对数ab 组贡献 \( C(2,2) = 1 \) 对,ac 组贡献 0 → **总对数 1**。

输入 2

4 3
cat
act
tac
dog
  • 标准化结果["act", "act", "act", "dgo"]Counter({'act': 3, 'dgo': 1})

  • 计算对数act 组贡献 \( C(3,2) = 3 \) 对 → **总对数 3**。


潜在问题

1. 不检查字符串长度

代码假设所有输入的字符串长度均为 m,若实际输入字符串长度不一致,标准化结果可能错误。

2. 未显式处理 v > 1

虽然组合数公式在 v ≤ 1 时结果为 0,但显式添加条件 if v > 1 可提升代码可读性:

for k, v in c.items():
    if v > 1:
        count += v * (v - 1) // 2

复杂度分析

步骤

时间复杂度

说明

标准化处理

\( O(n \cdot m \log m) \)

每个字符串排序耗时 \( O(m \log m) \)

统计标准化字符串

\( O(n) \)

遍历所有字符串

计算对数

\( O(k) \)

k 为不同标准化组的数量

总时间复杂度:\( O(n \cdot m \log m) \),适用于中等规模数据。


改进建议

  1. 显式检查字符串长度

    for s in a:
        if len(s) != m:
            raise ValueError("字符串长度不符合要求")
  1. 优化可读性添加条件判断 if v > 1 明确逻辑意图。


总结

  • 核心思想:通过标准化将字母异位词分组,统计每组内字符串对的组合数。

  • 适用场景:统计互为字母异位词的字符串对数目(如 LeetCode 49. Group Anagrams)。

  • 优化点:显式处理边界条件以提升代码健壮性。

**???大衣的最高分数

为了解决这个问题,我们需要确定对于每个给定的整数 K,从数组中选择元素以获得最高分数的策略。通过分析,我们可以发现每次选择当前桶中的最大值可以确保总分最大。通过数学推导,我们可以将问题转化为求数组前 N-K+1 个最大元素的和。

方法思路

1. **排序数组**:将数组按降序排列,以便于后续计算前 N-K+1 个最大元素的和。

2. **计算前缀和**:对排序后的数组计算前缀和,这样可以快速求出前若干个最大元素的和。

3. **生成结果**:对于每个 K,计算对应的 N-K+1,并利用前缀和数组快速得到结果。

### 解决代码

```python
n = int(input())
a = list(map(int, input().split()))
a.sort(reverse=True)
prefix = [0] * (n + 1)
for i in range(1, n + 1):
    prefix[i] = prefix[i-1] + a[i-1]
result = []
for k in range(1, n + 1):
    s = n - k + 1
    result.append(str(prefix[s]))
print(' '.join(result))
```

代码解释

1. **输入处理**:读取输入的数组长度和数组元素。

2. **排序**:将数组按降序排列,以便后续处理。

3. **前缀和计算**:计算排序后数组的前缀和数组,用于快速查询前若干个元素的和。

4. **生成结果**:对于每个 K 值,计算对应的前 N-K+1 个最大元素的和,并生成结果字符串输出。

这种方法的时间复杂度主要由排序操作决定,为 O(N log N),前缀和计算和结果生成的时间复杂度均为 O(N),整体高效且适用于较大的输入规模。

新一的晚餐挑战

方法思路

  1. 输入处理:读取输入的数组长度 N 和需要选择的元素数目 K,以及两个数组,分别表示菜的系列和对应的烹饪时间。

  2. 合并与排序:将菜的系列和对应的烹饪时间合并为一个列表,并按菜的系列排序,以便后续处理。

  3. 记录最小时间:遍历排序后的列表,记录每个菜系列的最小烹饪时间。

  4. 检查与计算:检查记录的最小时间数量是否足够,若足够则排序后取前 K 个最小时间求和,否则输出 -1。

解决代码

n,k = map(int,input().split())
a = list(map(int,input().split()))
b = list(map(int,input().split()))
ab = []

for i in range(n):
    ab.append([a[i],b[i]])
ab.sort()

pre_a = 0 # 记录上一个菜品的结束时间
cnt = 0  # 用于统计已选择的菜品类型的数量
time = []
for i,j in ab:
    if i > pre_a:
        pre_a = i
        time.append(j)
time.sort()
ans = 0
for i in time:
    ans+=i
    cnt+=1
    if cnt == k:
        break
if cnt<k:
    print(-1)
else:
    print(ans)

代码解释

  1. 输入处理与合并排序:将菜的系列和时间合并为元组列表,并按系列排序,以便处理同一系列的连续元素。

  2. 遍历记录最小时间:使用 pre_a 记录当前处理的系列,current_min 记录当前系列的最小时间。遍历过程中,遇到新系列时将前一个系列的最小时间存入列表,并重置当前系列和最小时间。遇到同一系列时更新最小时间。

  3. 处理最后一个系列:遍历结束后,将最后一个系列的最小时间存入列表。

  4. 检查与计算:若最小时间数量不足 K 种,输出 -1;否则排序后取前 K 个求和并输出。

该方法通过一次遍历即可记录每个系列的最小时间,时间复杂度主要由排序操作决定,为 O(N log N),适用于较大的输入规模。

基德与鲁邦的婚礼狂欢

n = int(input())
n_boy = sorted(list(map(int,input().split())),reverse = True)
n_gitrl = sorted(list(map(int,input().split())))
c = []
for i in range(n):
    c.append(n_boy[i]+n_gitrl[i])
print(max(c))
  1. 一个整数 n,表示男生和女生的数量。

  2. 一个包含 n 个整数的列表 n_boy,表示男生的属性值。

  3. 一个包含 n 个整数的列表 n_gitrl(应为 n_girl,拼写错误),表示女生的属性值。

代码逻辑分析

  1. 输入处理

    1. 读取 n

    2. 读取男生的属性值列表 n_boy,并将其降序排序(reverse=True)。

    3. 读取女生的属性值列表 n_gitrl,并将其升序排序(默认)。

  1. 配对求和

    1. 初始化一个空列表 c

    2. 遍历 n 次,每次将男生和女生列表中对应位置的属性值相加,结果存入 c

  1. 输出结果

    1. 输出列表 c 中的最大值。

代码的问题

  1. 变量名拼写错误n_gitrl 应为 n_girl

  2. 配对策略

    1. 当前策略是将男生列表降序排序后的元素与女生列表升序排序后的元素按顺序配对。这种策略的目的是让最大的男生属性值与最小的女生属性值配对,从而使得每对的和尽可能均匀分布,最终的最大和尽可能小。

    2. 这种策略在大多数情况下是有效的,但需要确保配对后的最大值确实是所有可能配对方式中最小的最大值。

改进建议

  1. 修正变量名:将 n_gitrl 改为 n_girl

  2. 验证配对策略

    1. 确保这种配对方式确实能得到最小的最大和。可以通过数学归纳法或举例验证。

    2. 例如:

      • 男生属性值:[5, 3, 1](降序排序后)。

      • 女生属性值:[1, 2, 3](升序排序后)。

      • 配对和:5+1=6, 3+2=5, 1+3=4,最大和为 6

      • 其他配对方式可能得到更大的最大和,如 5+3=8

修正后的代码

n = int(input())
n_boy = sorted(list(map(int, input().split())), reverse=True)
n_girl = sorted(list(map(int, input().split())))
c = []
for i in range(n):
    c.append(n_boy[i] + n_girl[i])
print(max(c))

总结

这段代码的核心思想是通过贪心算法,将最大的男生属性值与最小的女生属性值配对,以最小化每对和的最大值。这种策略在大多数情况下是有效的,但需要确保输入数据的排序和配对方式正确。修正变量名后,代码的逻辑更加清晰和准确。

黛玉泡茶【算法赛】

from math import *
n,m,k = map(int,input().split())
a = list(map(int,input().split()))
a.sort()
sus = sum(a[:k])
print(ceil(sus/m))

这段代码的功能是计算数组中前 z 个最小元素的总和,并将该总和除以 m 后向上取整。以下是分步解释:


输入说明

  • 输入格式

    • 第一行:三个整数 n(数组长度)、m(除数)、z(需选取的元素个数)。

    • 第二行:包含 n 个整数的数组 a

代码逻辑

  1. 排序数组

    a.sort()  # 将数组按升序排列,确保最小的元素在前
    • 例如:输入 a = [5, 7],排序后仍为 [5, 7]

  1. 计算最小和

    sus = sum(a[:z])  # 取前 z 个元素(最小的 z 个数)并求和
    • 例如:z=1 时,取 [5],和为 5

  1. 向上取整除法

    print(ceil(sus / m))  # 总和除以 m,结果向上取整
    • 例如:5 / 3 ≈ 1.666 → 向上取整为 2


样例验证

输入

2 3 1
5 7

执行步骤

  1. 排序数组:a = [5, 7](已有序)。

  2. 取前 z=1 个元素:[5],和为 5

  3. 计算 5 / 3 = 1.666...,向上取整得 2

  4. 输出结果:**2**。


关键点

  • 排序目的:确保选择最小的 z 个数。

  • 向上取整的意义:保证结果满足实际需求(如资源分配时避免小数)。

  • 公式等价性ceil(a / b) 可用 (a + b - 1) // b 替代(无需导入 math):

    print((sus + m - 1) // m)  # 与 ceil(sus/m) 结果相同

适用场景

  • 资源分组:例如将最小的 z 个任务分配给 m 个工人,每人最多承担多少总工作量。

  • 负载均衡:最小化最大负载时,计算资源分配的上限。


输出结果

对于样例输入,代码的输出为 **2**。

小蓝喜欢美丽的星星

n = int(input())
a = list(map(int, input().split()))
a.sort()
ans = a[n-1]
l, r = 0, n-2
while l < r:
    ans += a[r]
    r -= 1  # 必须更新指针
    l += 1  # 必须更新指针
print(ans)

注意事项:

  • l += 1r -= 1 的作用:确保双指针向中间移动,避免无限循环。

  • 去掉它们的后果:程序无法终止,导致运行超时(TLE)。

  • 正确性验证:通过移动指针,确保每次循环处理新的元素,最终得到正确结果。

代码逻辑分析

  1. 输入处理与排序

    1. 首先读取星星的数量 n 和美丽值数组 a

    2. 对数组 a 进行升序排序。例如,输入 [4,3,2,1] 排序后变为 [1,2,3,4]

  1. 初始化答案

    1. 将答案 ans 初始化为排序后数组的最后一个元素,即最大值。例如,ans = 4

  1. 双指针遍历

    1. 初始化两个指针 lr

      • l 从数组开头(索引 0)开始。

      • r 从数组倒数第二个元素(索引 n-2)开始。

    2. 循环条件:l < r

    3. 每次循环:

      • a[r] 的值加到 ans 中。

      • r 左移(r -= 1)。

      • l 右移(l += 1)。

    4. 例如,a = [1,2,3,4]

      • 初始 ans = 4l = 0r = 2a[r] = 3)。

      • 第一次循环:ans += 3ans = 7),r = 1l = 1

      • 第二次循环:l < r 不成立,循环结束。

  1. 输出结果

    1. 打印最终的 ans 值。例如,输出 7

正确性证明

  • 问题转化:题目允许交换星星位置和合并相邻星星,实际上可以通过排序和贪心策略找到最优解。

  • 贪心策略:每次合并时选择当前最大的星星及其相邻的星星,可以确保最终剩下的星星美丽值最大。

  • 数学归纳:通过排序后取最大的 (n+1)//2 个星星的美丽值之和,可以覆盖所有可能的合并操作的最优解。

示例验证

  1. 输入[4,3,2,1]

    1. 排序后:[1,2,3,4]

    2. 初始 ans = 4

    3. 第一次循环:ans += 3ans = 7),r = 1l = 1

    4. 循环结束,输出 7,与样例一致。

  1. 输入[5,4,3,2,1]

    1. 排序后:[1,2,3,4,5]

    2. 初始 ans = 5

    3. 第一次循环:ans += 4ans = 9),r = 2l = 1

    4. 第二次循环:ans += 3ans = 12),r = 1l = 2

    5. 循环结束,输出 12

为什么需要 l += 1r -= 1

  • 避免无限循环:如果不更新指针 lr,循环条件 l < r 将永远成立,导致程序无法终止,最终运行超时(TLE)。

  • 确保正确遍历:通过移动指针,确保每次循环处理新的元素,最终覆盖所有需要合并的星星。

时间复杂度

  • 排序O(n log n)

  • 双指针遍历O(n)

  • 总复杂度O(n log n),适用于题目给定的约束条件。

最终代码

n = int(input())
a = list(map(int, input().split()))
a.sort()
ans = a[n-1]
l, r = 0, n-2
while l < r:
    ans += a[r]
    r -= 1
    l += 1
print(ans)

总结

这段代码通过排序和贪心策略,高效地解决了问题。关键点在于:

  1. 排序:确保可以贪心地选择最大的星星。

  2. 双指针遍历:高效地累加需要合并的星星的美丽值。

  3. 指针更新:避免无限循环,确保程序正确终止。

最小步数【省模拟赛】

import math
n = int(input())
print(math.ceil(n/3))

裁纸刀

print(4+440-1)

¥¥小郑花式喝酒

这段代码解决的是一个关于 分配酒杯酒量 的问题,具体要求如下:

  1. 输入

    1. n:酒杯的数量。

    2. win:一个长度为 n 的列表,表示每个酒杯当前的酒量。

  1. 输出

    1. 如果可以通过调整(倒酒或喝酒)使得酒杯的酒量 **严格递增**(即 win[0] < win[1] < ... < win[n-1]),则输出 **最多能喝掉的酒量**。

    2. 如果无法满足严格递增条件,则输出 -1


关键逻辑分析

1. 严格递增的最小酒量需求

  • 为了使酒杯的酒量严格递增,最小的分配方式是:

\[

\text{第 } i \text{ 杯的酒量} \geq i \quad (i = 1, 2, \dots, n)

\]

  • 例如 n=3 时,最小分配为 [1, 2, 3],总和为 1 + 2 + 3 = 6

  • 最小总需求公式

\[

\text{最小需求} = 1 + 2 + \dots + n = \frac{n(n+1)}{2}

\]

  • 代码中通过 (n + 1) * n // 2 计算。

2. 判断是否可行

  • 总酒量 **s = sum(win)**

    • 如果 s < (n+1)*n//2,说明当前酒量不足以分配成严格递增序列,输出 -1

    • 否则,输出 s - (n+1)*n//2(即 **可喝掉的酒量**)。

3. 为什么 s - (n+1)*n//2 是可喝掉的酒量?

  • 初始酒量 s 是固定的。

  • 最小需求 (n+1)*n//2 是必须保留的酒量。

  • 因此,**多余的酒量 ****s - (n+1)*n//2** 就是可以喝掉的部分。


代码逐行解释

n = int(input())  # 输入酒杯数量
win = list(map(int, input().split()))  # 输入每个酒杯的酒量
s = sum(win)  # 计算总酒量

# 检查是否满足最小需求
if s < (n + 1) * n // 2:
    print(-1)  # 不满足,输出 -1
else:
    print(s - n * (n + 1) // 2)  # 满足,输出可喝掉的酒量

示例验证

示例 1:满足严格递增

  • 输入

    3
    2 3 4
  • 计算

    • n = 3,最小需求 (3+1)*3//2 = 6

    • 总酒量 s = 2 + 3 + 4 = 9

    • s - 6 = 3,因此可以喝掉 3 单位酒。

  • 输出

    3

示例 2:不满足严格递增

  • 输入

    3
    1 1 1
  • 计算

    • 最小需求 6,总酒量 s = 3

    • 3 < 6,无法满足条件。

  • 输出

    -1

常见问题解答

1. 为什么最小需求是 **(n+1)*n//2**

  • 这是自然数求和公式,表示严格递增序列的最小总酒量。例如:

    • n=31 + 2 + 3 = 6

    • n=41 + 2 + 3 + 4 = 10

2. 如果酒杯酒量已经是严格递增的,会输出什么?

  • 输出 0(因为 s = (n+1)*n//2,可喝掉的酒量为 0)。

3. 这段代码的时间复杂度是多少?

  • O(n)(因为 sum(win) 需要遍历列表一次)。


总结

  • 核心公式(n + 1) * n // 2 是严格递增序列的最小总酒量。

  • 判断逻辑

    • 如果总酒量不足,输出 -1

    • 否则,输出多余的酒量(可喝掉的部分)。

  • 适用场景:需要将酒量调整为严格递增或递减的问题。

新生

print(len("我于窗中窥伤鹤,恰如仰头见春台"))

数位和【省模拟赛】

什么是质数

质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数(规定1既不是质数也不是合数)。

def is_pream(a):
  if a <2 :
    return False
  for i in range(2,int(a**0.5)+1):
    if a % i == 0:
      return False
  return True

cout = 0
for i in range(1,1000001):
  ct = 0
  if is_pream(i):
    st = str(i)
    for j in st:
      ct+=int(j)
    if ct == 23:
      cout +=1
print(cout)
count = 0

for n in range(2, 1000001):
    # 计算各位数字之和
    temp = n
    sum_digits = 0
    while temp > 0:
        sum_digits += temp % 10
        temp = temp // 10
    if sum_digits != 23:
        continue
    
    # 跳过偶数(除了2,但2的各位和不是23)
    if n % 2 == 0:
        continue
    
    # 判断是否为质数
    is_prime = True
    sqrt_n = int(n ** 0.5) + 1
    for i in range(3, sqrt_n, 2):
        if n % i == 0:
            is_prime = False
            break
    if is_prime:
        count += 1

print(count)

统计次数

a = input()
for i in range(0,10):
    b = a.count(str(i))
    print(b,end=' ')

代码功能解释

这段代码的作用是:

  1. a = input()

    1. 让用户输入一个字符串(比如输入 "1234567890"),并赋值给变量 a

  1. for i in range(0, 10):

    1. 循环 i09(共 10 次),依次检查 09 每个数字在字符串 a 中出现的次数。

  1. b = a.count(str(i))

    1. str(i):把当前循环变量 i(数字 0~9)转换成**字符串类型**,因为 a 是字符串,count() 方法只能统计**子字符串**出现的次数。

    2. a.count(str(i)):计算字符串 a 中包含多少个 i(比如 i=3,就统计 "3"a 中出现的次数)。

  1. print(b, end=' ')

    1. 打印每个数字 i 的出现次数 b,并用空格分隔(end=' ' 表示不换行)。


为什么 str(i) 是必要的?

  • a** 是字符串**,而 i 是整数(0, 1, 2, ..., 9)。

  • count()** 方法只能统计子字符串**,不能直接统计数字。

    • ❌ 错误写法:a.count(i)(会报错,因为 i 是数字,不是字符串)。

    • ✅ 正确写法:a.count(str(i))(把 i 转成字符串再统计)。


示例运行结果

如果用户输入 "112233",程序会输出:

2 2 2 0 0 0 0 0 0 0

解释:

  • '0' 出现 0

  • '1' 出现 2

  • '2' 出现 2

  • '3' 出现 2

  • '4''9' 均出现 0


总结

  • str(i)** 的作用**:把数字 i 转换成字符串,才能用 count() 统计它在 a 中出现的次数。

  • 适用场景:统计用户输入的字符串中 0~9 每个数字的出现频率。

如果想统计字母或其他字符,可以修改循环范围或逻辑。

最尖位置

题解

n = int(input())
a = list(map(int,input().split()))
res = 0
for i in range(1,n-1):
    if a[i] < a[i-1] and a[i]<a[i+1]:
        res = max(res,(a[i-1]-a[i])*(a[i+1]-a[i]))
print(res)

最大落差

import os
import sys

# 请在此输入您的代码

n = int(input())
a = list(map(int,input().split()))
res = 0
for i in range(1,len(a)-1):
    if a[i+1]<a[i]:
        res = max(res,(a[i]-a[i+1]))
print(res)