日常刷题(6)

1. 分披萨

1.1. 题目描述

"吃货"和"馋嘴"两人到披萨店点了一份铁盘(圆形)披萨,并嘱咐店员将披萨按放射状切成大小相同的偶数个小块。但是粗心的服务员将披萨切成了每块大小都完全不同奇数块,且肉眼能分辨出大小。

由于两人都想吃到最多的披萨,他们商量了一个他们认为公平的分法:从"吃货"开始,轮流取披萨。除了第一块披萨可以任意选取外,其他都必须从缺口开始选。

他俩选披萨的思路不同。"馋嘴"每次都会选最大块的披萨,而且"吃货"知道"馋嘴"的想法。

已知披萨小块的数量以及每块的大小,求"吃货"能分得的最大的披萨大小的总和。

我先选披萨,对方从我那块两侧选最大的,求我最多能拿到多少

1.2. 输入描述

第 1 行为一个正整数奇数 N,披萨块数量。

3 ≤ N < 500
接下来的第 2 行到第 N + 1 行(共 N 行),每行为一个正整数,表示第 i 块披萨的大小

1 ≤ i ≤ N
披萨小块从某一块开始,按照一个方向次序顺序编号为 1 ~ N

每块披萨的大小范围为 [1, 2147483647]

1.3. 输出描述

"吃货"能分得到的最大的披萨大小的总和。

1.4. 用例

输入 5(n块披萨)
8
2
10
5
7
输出 19
说明
此例子中,有 5 块披萨。每块大小依次为 8、2、10、5、7。
按照如下顺序拿披萨,可以使"吃货"拿到最多披萨:
“吃货” 拿大小为 10 的披萨
“馋嘴” 拿大小为 5 的披萨
“吃货” 拿大小为 7 的披萨
“馋嘴” 拿大小为 8 的披萨
“吃货” 拿大小为 2 的披萨
至此,披萨瓜分完毕,"吃货"拿到的披萨总大小为 10 + 7 + 2 = 19
可能存在多种拿法,以上只是其中一种。

1.5. 题目解析

大力出奇迹 —— 递归

1.6. 代码

from functools import cache


class Solution:
    @cache
    def choose_pizza(self, pizza: str, ans: int = 0) -> int:
        pizza = eval(pizza)  # @cache函数不接受list数据类型
        if not pizza:
            return 0

        # 对方选择最大的一块
        index = pizza.index(max(pizza[0], pizza[-1]))
        pizza.pop(index)

        # 我方尝试左右两边
        max_ans = 0
        for side in [0, -1]:
            size = pizza.pop(side)
            _ans = ans + size + self.choose_pizza(str(pizza), ans)
            max_ans = max(max_ans, _ans)
			
			# 回溯
            pizza.insert(side, size)

        return max_ans

    def __call__(self, pizza: List[int]):
        max_ans = 0
        for i, pizza_size in enumerate(pizza):
            _pizza = pizza[i + 1:] + pizza[:i]
            ans = self.choose_pizza(str(_pizza)) + pizza_size
            max_ans = max(ans, max_ans)
        return max_ans

2. 工号不够用了怎么办?

2.1. 题目描述

3020年,空间通信集团的员工人数突破20亿人,即将遇到现有工号不够用的窘境。
现在,请你负责调研新工号系统。继承历史传统,新的工号系统由小写英文字母(a-z)和数字(0-9)两部分构成。
新工号由一段英文字母开头,之后跟随一段数字,比如”aaahw0001″,”a12345″,”abcd1″,”a00″。
注意新工号不能全为字母或者数字,允许数字部分有前导0或者全为0。
但是过长的工号会增加同事们的记忆成本,现在给出新工号至少需要分配的人数X和新工号中字母的长度Y,求新工号中数字的最短长度Z。

2.2. 输入描述

一行两个非负整数 X Y,用数字用单个空格分隔。
0< X <=2^50 – 1
0< Y <=5

2.3. 输出描述

输出新工号中数字的最短长度Z

2.4. 用例

输入 260 1
输出 1

输入 26 1
输出 1
说明 数字长度不能为0

输入 2600 1
输出 2
说明 无

2.5. 题目解析

注意是数字要短,那么字母就要多一点。y全用上就好
x ≤ 2 6 y + 1 0 z log ⁡ x 2 6 y ≤ z x \leq 26^y + 10^z \\ \log{\frac{x}{26^y}} \leq z x26y+10zlog26yxz

2.6. 代码

import math
def solution(x, y):
	z = math.log10(x / math.pow(26, y))
	return max(1, math.ceil(z))

3. 勾股数元组

3.1. 题目描述

如果3个正整数(a,b,c)满足a^2 + b^2 = c^2的关系,则称(a,b,c)为勾股数(著名的勾三股四弦五),

为了探索勾股数的规律,我们定义如果勾股数(a,b,c)之间两两互质(即a与b,a与c,b与c之间均互质,没有公约数),则其为勾股数元组(例如(3,4,5)是勾股数元组,(6,8,10)则不是勾股数元组)。

请求出给定范围[N,M]内,所有的勾股数元组。

3.2. 输入描述

起始范围N,1 <= N <= 10000

结束范围M,N < M <= 10000

3.3. 输出描述

  1. a,b,c请保证a < b < c,输出格式:a b c;

  2. 多组勾股数元组请按照a升序,b升序,最后c升序的方式排序输出;

  3. 给定范围中如果找不到勾股数元组时,输出”NA“。

3.4. 用例

输入
1
20
输出 3 4 5
5 12 13
8 15 17
说明
[1,20]范围内勾股数有:(3 4 5),(5 12 13),(6 8 10),(8 15 17),(9 12 15),(12 16 20);
其中,满足(a,b,c)之间两两互质的勾股数元组有:(3 4 5),(5 12 13),(8 15 17);
按输出描述中顺序要求输出结果。

输入
5
10
输出 NA
说明
[5,10]范围内勾股数有:(6 8 10);
其中,没有满足(a,b,c)之间两两互质的勾股数元组;
给定范围中找不到勾股数元组,输出”NA“

3.5. 题目解析

  1. 找到勾股数
    先将每个数的平方计算保存到arr,分别遍历i和j,如果两个数之和在arr中就是勾股数。
  2. 判断是否互为质数
    GPT说可以用GCD方法判断

3.6. 代码

import math
import itertools

class Solution:
    def is_coprime(self, a, b):
        while b:
            a, b = b, a % b
        return a == 1

    def check_coprime(self, a, b, c):
        return all(map(lambda x: self.is_coprime(*x), itertools.combinations((a, b, c), 2)))

    def __call__(self, n, m):
        arr = list(map(lambda x: x ** 2, range(n, m)))

        result = []
        for i in range(n, m):
            for j in range(i + 1, m):
                square = i ** 2 + j ** 2
                if square not in arr:
                    continue
                k = math.ceil(math.sqrt(square))
                if not self.check_coprime(i, j, k):
                    continue
                result.append([i, j, k])
        return result

4. 冠亚军排名,奖牌榜排名

4.1. 题目描述

假设奖牌榜的排名规则如下:

首先gold medal数量多的排在前面
其次silver medal数量多的排在前面
然后bronze medal数量多的排在前面
若以上三个条件仍无法区分名次,则以国家名称的字典顺序排定。
我们假设国家名称不超过二十个字符,各类奖牌数不超过100,且大于0.

4.2. 输入描述

第一行输入一个整数N(0<N<21),代表国家数量,

然后接下来的N行,每行包含:

一个字符串Name表示各个国家的名称和三个整数Gi,Si,Bi表示每个获得的gold medal,silver medal,bronze medal的数量,以空格隔开,如(China 51 20 21),

具体见样例输入。
China 32 28 34
England 12 34 22
France 23 33 2
Japan 12 34 25
Rusia 23 43 0

4.3. 输出描述

输出奖牌榜的依次顺序,只输出国家名称,各占一行,具体见样例输出。

China
Rusia
France
Japan
England

4.4. 用例

输入
China 32 28 34
England 12 34 22
France 23 33 2
Japan 12 34 25
Rusia 23 43 0
输出 China
Rusia
France
Japan
England

4.5. 代码

class Solution:
    def __call__(self, countries: List):
        info = [country.split() for country in countries]
        info = [(-int(g), -int(s), -int(b), country) for (country, g, s, b) in info]
        info.sort()
        return list(map(lambda x: x[-1], info))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值