2023蓝桥杯python大学A组部分题目详细解析

目录

特殊日期

分糖果

三国游戏

平均


特殊日期

记一个日期为yy年mm月dd 日,统计从2000年1月1日(含)到2000000年1月1日(含),有多少个日期满足年份yy是月份mm的倍数,同时也是dd的倍数。

题目链接

https://www.lanqiao.cn/problems/3495/learning/?page=1&first_category_id=1&sort=students_count&category_id=3&name=%E7%89%B9%E6%AE%8A%E6%97%A5%E6%9C%9F

典型的使用枚举思想,可以从2000年1月1日(含)到2000000年1月1日(含)每天是否符合特殊日期的要求进行枚举,符合条件计数就加1

mouth1 = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]  # 平年每个月天数列表,这里为了与月份统一下标,所以第一个为0
mouth2 = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]  # 闰年每个月天数列表


def fun(x):  # 判断闰年函数
    if (x % 4 == 0 and x % 100 != 0) or x % 400 == 0:  # 能被4整除且不能被100整除,或者能被400整除
        return 1
    else:
        return 0


ans = 0
for i in range(2000, 2000000):
    for j in range(1, 13):  # 月份从1到12
        if fun(i) == 0:  # 如果是平年
            for m in range(1, mouth1[j] + 1):  # 日期从1到mouth[j]
                if i % j == 0 and i % m == 0:  # i表示年份,j表示月份,m表示日期
                    ans = ans + 1
        if fun(i) == 1:  # 如果是闰年
            for n in range(1, mouth2[j] + 1):
                if i % j == 0 and i % n == 0:
                    ans = ans + 1
print(ans + 1)# 由于2000000.1.1以上循环没有但是也满足,所以要加上
# 35813063

这里使用定义每个月份的天数的列表可以简化后面的代码,这个思想对做这种时间题很有帮助

遇到时间问题还是一种思想就是可以使用datetime类,是python非常好用的用于计算时间的自带类,该类的使用方法可以查看我上次发的资源

https://download.csdn.net/download/m0_62574258/88760682

例如下题

对于一个日期,我们可以计算出年份的各个数位上的数字之和,也可以分别计算月和日的各位数字之和。请问从1900年1月1日至9999年12月31日,年份的数位数字之和等于月的数位数字之和加日的数位数字之和。例如,2022年11月13日满足要求,因为2+0+2 +2 =(1+1)+(1+3)。请提交满足条件的日期的总数量。

import datetime


def fun(x):
    return sum(int(i) for i in str(x))  # 定义fun函数,用于计算数字的和


# 定义开始和结束日期范围
d1 = datetime.datetime(1900, 1, 1)
d2 = datetime.datetime(9999, 12, 31)
# 计算开始和结束日期之间的总天数
y = (d2 - d1).days
ans = 0

# 遍历日期范围内的每一天
for i in range(y):
    # 从当前日期中提取年、月和日
    a = d1.year
    b = d1.month
    c = d1.day

    # 检查年份的数字和是否等于月份数字和加上日期数字和
    if fun(a) == fun(b) + fun(c):
        ans = ans + 1

    # 使用一天的时间增量移动到下一天
    d1 = d1 + datetime.timedelta(days=1)

# 打印结果
print(ans)

分糖果

两种糖果分别有 9 个和 16 个,要全部分给 7 个小朋友,每个小朋友得到的糖果总数最少为 2 个最多为 5 个,问有多少种不同的分法。 只要有其中一个小朋友在两种方案中分到的糖果不完全相同,这两种方案就算作不同的方案。

题目链接

https://www.lanqiao.cn/problems/4124/learning/?page=1&first_category_id=1&sort=students_count&category_id=3&name=%E5%88%86%E7%B3%96%E6%9E%9C

使用递归思想,对于每个孩子使用两个for循环分配两种糖果的个数,当一个孩子分配完时再递归分配下一个孩子,此时糖果数量要对应的扣除上次分配出去的,如果7个孩子都分配完且糖果没有剩余,则算一种方案

ans = 0


def dfs(child, n, m):
    global ans  # 先声明ans是全局变量,否则函数内部的操作变量ans不会影响到函数外的ans
    if child == 0 and n == 0 and m == 0:  # 如果孩子数和两种糖果都分配完了即满足条件
        ans += 1
    for i in range(n + 1):  # 第一种糖果
        for j in range(m + 1):  # 第二种糖果
            if 2 <= i + j <= 5:
                dfs(child - 1, n - i, m - j)  # 继续递归对下一个孩子进行分配


dfs(7, 9, 16)  # 7个孩子,第一种糖果有9个,第二种糖果有16个
print(ans)
#5067671

三国游戏

小蓝正在玩一款游戏。游戏中魏(X)、蜀(Y)、吴(Z)三个国家各自拥有一定数量的士兵X,Y,Z(一开始可以认为都为0)。游戏有n个可能会发生的事件,每个事件之间相互独立且最多只会发生一次,当第i个事件发生时会分别让X,Y ,Z增加Ai,Bi,Ci,当游戏结束时(所有事件的发生与否已经确定),如果X,y,Z的其中一个大于另外两个之和,我们认为其获胜。例如,当X >Y +Z时,我们认为魏国获胜。小蓝想知道游戏结束时如果有其中一个国家获胜,最多发生了多少个事件?如果不存在任何能让某国获胜的情况,请输出-1。

输入格式

输入的第一行包含一个整数n。

第二行包含n个整表示Ai,相邻整数之间使用一个空格分隔。

第三行包含n个整数表示Bi,相邻整数之间使用一个空格分隔。

第四行包含n个整数表示Ci,相邻数之间使用一个空格分隔。

样例输入

3
1 2 2
2 3 2
1 0 7

样例输出:2

题目链接

https://www.lanqiao.cn/problems/3518/learning/?page=1&first_category_id=1&sort=students_count&category_id=3&name=%E4%B8%89%E5%9B%BD%E6%B8%B8%E6%88%8F

这里有个技巧就是每次三个国家都会增加,我们只需要计算相对增加量,然后对三个国家各自胜利分类讨论,因为我们可以控制哪些事件先发生哪些事件后发生,所以最后只需要使用贪心算法的思想,相对增量越少的时间越先发生就能使用最多的事件数

n = int(input())
a = list(map(int, input().split()))
b = list(map(int, input().split()))
c = list(map(int, input().split()))
x = []
y = []
z = []
for i in range(n):
    x.append(a[i] - b[i] - c[i])  # 存储每个事件魏国相比较其它两国的相对增量
    y.append(b[i] - a[i] - c[i])  # 存储每个事件蜀国国相比较其它两国的相对增量
    z.append(c[i] - a[i] - b[i])  # 存储每个事件吴国相比较其它两国的相对增量
    # 由于三国一开始都是0,所以只要当所有发生事件的相对增量和大于0即胜利
    # 将相对增量排序,要求最大发生事件数,应该让相对增量为正数全部发生,然后相对增量为负数的从大到小发生,直到相对增量和大于0
    # 可以认为所有事件按贡献的大小从大到小的顺序发生,所以将相对增量降序排序
    x.sort(reverse=True)
    y.sort(reverse=True)
    z.sort(reverse=True)


def win(p):  # 求p国获胜的最大发生事件数
    sum = 0
    for i in range(n):
        sum = sum + p[i]
        if sum < 0:
            return i
    return 0


print(max(win(x), win(y), win(z)))  # 依次求x国、y国、z国胜利的最大发生事件数,然后再取最大值

平均

有一个长度为n的数组(n是10的倍数),每个数a都是区间[0,9]中的整数。小明发现数组里每种数出现的次数不太平均,而更改第i个数的代价为bi,他想更改若干个数的值使得这10种数出现的次数相等(都等于n/10),请问代价和最少为多少。

题目链接

https://www.lanqiao.cn/problems/3532/learning/?page=1&first_category_id=1&sort=students_count&category_id=3&name=%E5%B9%B3%E5%9D%87

输入格式

输入的第—行包含—个正整数n。

接下来n行,第i行包含两个整数ai,bi,用一个空格分隔。

样例输入

10
1 1
1 2
1 3
2 4
2 5
2 6
3 7
3 8
3 9
4 10

样例输出:27

还是使用贪心思想,从0到9开始遍历,看哪个数字的数量超过了n/10,某个数字超过平均个数多少个就要改多少个,而改哪几个是由代价决定的,代价越小越先被改变。这里使用二维列表,b列表中存放了10个一维列表,0到9每种数字的所有代价分别存在这10个一维列表

n = int(input())
sum = 0  # 代价和
b = [[] for i in range(10)]  # 创建二维列表,b[i]存储i数字的所有代价
for i in range(n):
    o, e = map(int, input().split())  # o是数字几,e是该数的代价
    b[o].append(e)  # 根据数字找到对应哪个列表,然后把该数的代价加入到该列表中

ave = n // 10
for i in range(10):  # 数字从0到9遍历
    if len(b[i]) > ave:  # len(b[i])表示i数字的个数,如果大于平均值,多出来的就要变成其他数
        num = len(b[i]) - ave  # 与平均值作差,差值num表示有多少个变成别的数
        b[i].sort()  # 将i数字的所有代价升序排序
        for j in range(num):  # 从中取代价最小的num个数,从开头开始取,一直取num个
            sum = sum + b[i][j]  # 把取出的数需要的代价加上sum

print(sum)

你可能感兴趣的:(蓝桥杯,python)