学习笔记,有些思路代码是看题解和博客
已更新:
1、纸张尺寸(大学B、C组)
2、数位排序(大学B、C组)
3、矩形拼接(研究生组、大学A、C组)
4、GCD(大学C组)
5、峰巢(大学B、C组)
6、消除游戏(研究生组、大学A、B组)
7、质因数个数(研究生组,大学A组)
纸张尺寸(大学B、C组)
1、题目
题目描述
在 ISO 国际标准中定义了 A0 纸张的大小为 1189mm × 841mm,将 A0 纸沿长边对折后为 A1 纸,大小为 841mm × 594mm,在对折的过程中长度直接取下整(实际裁剪时可能有损耗)。将 A1 纸沿长边对折后为 A2 纸,依此类推。 输入纸张的名称,请输出纸张的大小
输入格式
输入一行包含一个字符串表示纸张的名称,该名称一定是 A0、A1、A2、A3、A4、A5、A6、A7、A8、A9 之一。
输出格式
输出两行,每行包含一个整数,依次表示长边和短边的长度。
样例输入
A0
样例输出
1189 841
2、思路
(列表、元组)
可以写一个函数,知道输入数组的数字(第二个数,比如A0的0),就可以得到对应的长和宽,本函数返回值是元组。
对应的长宽可以根据一个for循环来得到,通过观察可知l=w,w=l/2。
在函数的后面写输入、输出就好了。
3、代码
def paper_size(name): len=int(name[1])#name是字符串,取第二个数值 l,w=1189,841#是0的话就直接返回 for _ in range(len):#是0的话直接不进入循环 l,w=w,l//2 return l,w name=input().strip() l,w=paper_size(name) print(l) print(w)
数位排序(大学B、C组)
1、题目
题目描述
小蓝对一个数的数位之和很感兴趣,今天他要按照数位之和给数排序。当两个数各个数位之和不同时,将数位和较小的排在前面,当数位之和相等时,将数值小的排在前面。
例如,2022 排在 409 前面,因为 2022 的数位之和是 6,小于 409 的数位之和 13。
又如,6 排在 2022 前面,因为它们的数位之和相同,而 6 小于 2022。
给定正整数 n,m,请问对 1 到 n 采用这种方法排序时,排在第 m 个的元素是多少?
输入格式
输入第一行包含一个正整数 n。
第二行包含一个正整数 m。
输出格式
输出一行包含一个整数,表示答案。
样例输入
13 5
样例输出
3
2、思路
(排序,数位之和)
第一步先写整数各个元素之和,用个函数封装起来。其思路是把整数转换为数组。
第二步是用排序函数sorted还有key,key是表示排序规则的
3、代码
#输入两个整数 n=int(input()) m=int(input()) #创建一个1到N的列表 s=[i for i in range(1,n+1)] #函数来求整数各个元素的和 def num_sum(a): sum=0 for i in str(a): sum+=int(i) return sum #排序数组,key表示排序规则,后面跟函数 s=sorted(s,key=num_sum) #输出别忘了 print(s[m-1])
矩形拼接(研究生组、大学A、C组)
1、题目
题目描述
已知 3 个矩形的大小依次是 a1 × b1, a2 × b2 和 a3 × b3。用这 3 个矩形能拼出的所有多边形中,边数最少可以是多少?例如用 3 × 2 的矩形(用 A 表示)、4 × 1 的矩形(用 B 表示)和 2 × 4 的矩形(用 C 表示)可以拼出如下 4 边形。
例如用 3 × 2 的矩形(用 A 表示)、3 × 1 的矩形(用 B 表示)和 1 × 1 的矩形(用 C 表示)可以拼出如下 6 边形。
输入格式
输入包含多组数据。
第一行包含一个整数 T,代表数据组数。
以下 T 行,每行包含 6 个整数 a1, b1, a2, b2, a3, b3,其中 a1, b1 是第一个矩形的边长,a2, b2 是第二个矩形的边长,a3, b3 是第三个矩形的边长。
输出格式
对于每组数据,输出一个整数代表答案。
样例输入
2 2 3 4 1 2 4 1 2 3 4 5 6
样例输出
4 6
2、思路
(for循环,枚举,数学问题)
首先得分类讨论
4条边情况:(1)3个矩形有一条相同的边(2)2个矩形的有一条边相同,且它们的另一条边也相同
6条边情况:(1)2个矩形有一条相同的边(2)2个矩形的有一条边相同,且它们的另一条边不同
8条边情况:除了上面两个的都是
(1)输入可以弄成列表形式
(2)枚举的话太多情况了,可以用暴力循环;第一个三层循环来确定矩阵,确保不重复;第二个三层循环来确定边,就可以用分类讨论里的情况,4比6多条件,可以先判断6再判断4
(3)ans很重要,默认是8,后面再修改
3、代码
#第一个输入 T = int(input()) #在循环里进行 while T: T -= 1 ans = 8 a = list(map(int, input().split())) a = [[a[0], a[1]], [a[2], a[3]], [a[4], a[5]]] #第一个三层循环是为了确定三个不同矩形 for i in range(3): for j in range(3): for k in range(3): if i == j or i == k or j == k:#确保是不同矩形 continue #第二个三层循环是为了确定不同矩形的边 for ii in range(2): for jj in range(2): for kk in range(2): #4比6多个条件,可以先判断6,后加条件判断4 if a[i][ii] == a[j][jj]: ans = min(ans, 6) if a[i][ii] == a[k][kk]: ans = min(ans, 4) #4比6多个条件,可以先判断6,后加条件判断4 if a[i][ii] == a[j][jj] + a[k][kk]: ans = min(ans, 6) if a[j][jj - 1] == a[k][kk - 1]: ans = min(ans, 4) print(ans)
GCD(大学C组)
1、题目
题目描述
给定两个不同的正整数 a, b,求一个正整数 k 使得 gcd(a + k, b + k) 尽可能大,其中 gcd(a, b) 表示 a 和 b 的最大公约数,如果存在多个 k,请输出所有满足条件的 k 中最小的那个。
输入格式
输入一行包含两个正整数 a, b,用一个空格分隔。
输出格式
输出一行包含一个正整数 k。
样例输入
5 7
样例输出
1
2、思路
(GCD变形)
求a,b的差值。考虑差值等于0和不为0情况,不为0时,返回c-a%c(我不太懂这个逻辑)
3、代码
a, b = map(int, input().split()) c = abs(b - a) if c == 0: print(0) else: print(c-a%c)
峰巢(大学B、C组)
1、题目
题目描述
蜂巢由大量的六边形拼接而成,定义蜂巢中的方向为:0 表示正西方向,1 表示西偏北 60◦,2 表示东偏北 60◦,3 表示正东,4 表示东偏南 60◦,5 表示西偏南 60◦。
对于给定的一点 O,我们以 O 为原点定义坐标系,如果一个点 A 由 O 点先向 d 方向走 p 步再向 (d + 2) mod 6 方向(d 的顺时针 120◦ 方向)走 q 步到达,则这个点的坐标定义为 (d, p, q)。在蜂窝中,一个点的坐标可能有多种。
下图给出了点 B(0, 5, 3) 和点 C(2, 3, 2) 的示意。
给定点 (d1, p1, q1) 和点 (d2, p2, q2),请问他们之间最少走多少步可以到达?
输入格式
输入一行包含 6 个整数 d1, p1, q1, d2, p2, q2 表示两个点的坐标,相邻两个整数之间使用一个空格分隔。
输出格式
输出一行包含一个整数表示两点之间最少走多少步可以到达。
样例输入
0 5 3 2 3 2
样例输出
7
2、思路
(数学,坐标转换)
在一篇博客找到的原理图。可以根据此图设计六个方向,x,y轴方向如图所示。
(1)先把x,y坐标的对应列表写好
在六边形坐标系中,每个方向对应着一个 x 坐标和一个 y 坐标的增量。具体来说,六个方向分别为:
0 表示正西方向
1 表示西偏北 60°
2 表示东偏北 60°
3 表示正东方向
4 表示东偏南 60°
5 表示西偏南 60°
在这个六边形坐标系中,每个方向都有一个对应的 x 坐标和 y 坐标增量,通过这些增量我们可以计算出每个方向上的点的坐标。增量的定义如下:
当方向为 0 时,x 坐标增量为 1,y 坐标增量为 0。
当方向为 1 时,x 坐标增量为 1,y 坐标增量为 1。
当方向为 2 时,x 坐标增量为 0,y 坐标增量为 1。
当方向为 3 时,x 坐标增量为 -1,y 坐标增量为 0。
当方向为 4 时,x 坐标增量为 -1,y 坐标增量为 -1。
当方向为 5 时,x 坐标增量为 0,y 坐标增量为 -1。
(2)把输入的d1.p1,q1......转换为x,y坐标
(3)判断是否在一条直线上,在的话直接坐标相减的最大值,不在的话最小值相加
3、代码
# 读取输入 d1, p1, q1, d2, p2, q2 = map(int, input().split()) # 定义x、y方向的增量 x = [1, 1, 0, -1, -1, 0] y = [0, 1, 1, 0, -1, -1] # 计算点A的坐标 xa = x[d1] * p1 + x[(d1 + 2) % 6] * q1 ya = y[d1] * p1 + y[(d1 + 2) % 6] * q1 # 计算点B的坐标 xb = x[d2] * p2 + x[(d2 + 2) % 6] * q2 yb = y[d2] * p2 + y[(d2 + 2) % 6] * q2 # 计算两点之间的最小步数 if xa == xb or ya == yb or (yb - ya) * (xb - xa) > 0: ans = max(abs(xa - xb), abs(ya - yb)) else: ans = abs(xa - xb) + abs(ya - yb) # 输出结果 print(ans)
消除游戏(研究生组、大学A、B组)
1、题目
题目描述
在一个字符串 S 中,如果 S i = S i−1 且
,则称 S i 和 S i+1 为边缘字符。如果 S i = S i−1且 S i = S i+1,则 S i−1 和 S i 也称为边缘字符。其它的字符都不是边缘字符。
对于一个给定的串 S,一次操作可以一次性删除该串中的所有边缘字符(操作后可能产生新的边缘字符)。
请问经过 264 次操作后,字符串 S 变成了怎样的字符串,如果结果为空则输出 EMPTY。
输入格式
输入一行包含一个字符串 S 。
输出格式
输出一行包含一个字符串表示答案,如果结果为空则输出 EMPTY。
样例输入
edda
样例输出
EMPTY
2、思路
(多个列表、for循环)
(1)创建两个新列表,一是把原字符转换成列表,二是创建标志列表,用来标记边缘字符
(2)弄一个大循环
(3)每次循环开始,都要重置标志列表和字符列表长度
(4)内循环遍历两种边缘字符的情况,边缘字符标志为1
(5)创建新列表,存储边缘字符
(6)更新列表和列表长度
(7)跳出条件(更新前后长度是否相等)
(8)跳出循环后,将列表连成字符串
3、代码
st = input() # 获取输入的字符串 st_list = list(st) # 将字符串转换为列表,方便操作 st_flag = [0 for _ in range(len(st_list))] # 创建标志列表,用于标记边缘字符 for c in range(2**64): # 循环次数,确保能够在有限时间内完成操作 st_flag = [0 for _ in range(len(st_list))] # 在每次循环开始时,将标志列表重新置零 l1 = len(st_list) # 记录循环开始时的字符列表长度 # 遍历字符串列表中的元素 for i in range(1, len(st_list) - 1): # 条件一:当前字符与前一个字符相同,且与后一个字符不同 if st_list[i] == st_list[i-1] and st_list[i] != st_list[i+1]: st_flag[i] = 1 # 将当前字符和后一个字符标记为边缘字符 st_flag[i+1] = 1 # 条件二:当前字符与前一个字符不同,且与后一个字符相同 if st_list[i] != st_list[i-1] and st_list[i] == st_list[i+1]: st_flag[i] = 1 # 将当前字符和前一个字符标记为边缘字符 st_flag[i-1] = 1 # 创建一个新的列表,用于存储非边缘字符 st_list2 = [] for i in range(len(st_flag)): if st_flag[i] == 0: st_list2.append(st_list[i]) # 将非边缘字符添加到新列表中 st_list = st_list2 # 更新字符串列表 l2 = len(st_list) # 删除边缘字符后的列表长度 # 如果删除边缘字符后的长度与之前的长度相同,则说明字符串里已经没有边缘字符了,可以跳出循环 if l2 == l1: break st = ''.join(st_list) # 将列表连接成字符串 # 输出结果,如果处理后的字符串为空,则输出'EMPTY' if len(st) == 0: print('EMPTY') else: print(st)
质因数个数
1、题目
题目描述
给定正整数 n,请问有多少个质数是 n 的约数。
输入格式
输入的第一行包含一个整数 n。
输出格式
输出一个整数,表示 n 的质数约数个数。
样例输入
396
样例输出
3
2、思路
首先写个函数判断是否为质数;其次判断是否为约数
3、代码
n = int(input().strip()) k = 0 def is_number(a): # 判断质数函数 if a <= 1: return False for i in range(2, a): if a % i == 0: return False return True for j in range(1, n): if is_number(j) and n % j == 0: # 调用 is_number 函数并传递参数 j k += 1 print(k)