最大公约数
给定一组正整数,问最少删除几个数,能保证剩下的数(数目大于1)的最大公约数为1。
- 输入描述
N,数组的长度,大于1
a1 a2 a3 … aN,数组元素 - 输出描述
最少删除元素的个数 - 示例
3
2 2 4
-1
2
1 2
0
解释:[2,2,4]不可能通过删除元素来使得最大公约数为1,所以输出-1;[1,2]本身最大公约数就为1,所以输出0。
数学题,要能分析出一组正整数的最大公约数(GCD)要么为1,要么不为1;不为1的一组数不论怎么样删除,数组元素的GCD都不可能为1。即解题思路就是判断这组数的GCD是否为1,时间复杂度为O(N),N是数组长度。
def gcd(a, b):
while b != 0:
t = a % b
a = b
b = t
return a
if __name__ == "__main__":
N = int(sys.stdin.readline().strip())
line = sys.stdin.readline().strip()
# 把每一行的数字分隔后转化成int列表
datas = list(map(int, line.split()))
a = datas[0]
for i in range(1, N):
b = datas[i]
a = gcd(a, b)
if a == 1:
break
if a == 1:
print(0)
else:
print(-1)
取模方程
给定两个非负整数a和b,问有多少个非负整数x,使a%x=b。
a和b属于[0, 1 0 9 10^9 109]
- 输入描述
a b - 输出描述
x的个数 - 示例
7 3
1
15 15
inf
解释:7 mod 4 = 3,x只有4这个取值满足要求,所以输出1;x取大于15的数都满足要求,所以有无数个,输出inf。
数学题。根据题意分类讨论可以得到下面的结论:1.当a==b,输出inf;2.当b>a,输出0;当a>b,符合要求的x属于(b,a-b],且是a-b的因子。
if __name__ == "__main__":
line = sys.stdin.readline().strip()
# 把每一行的数字分隔后转化成int列表
values = list(map(int, line.split()))
a, b = values[0], values[-1]
if a == b:
print("inf")
elif b > a:
print(0)
else:
max_x = a-b
count = 0
factor1 = 1
while factor1**2 <= max_x:
factor2, remainder = divmod(max_x, factor1)
if remainder == 0:
if factor1 > b:
count += 1
if factor2 > b and factor2 != factor1:
count += 1
factor1 += 1
print(count)
走迷宫
有一个N*M大小的迷宫,每一个格子用’.‘或’#‘表示,其中’.‘代表可通行的、’#‘表示是墙,现在问任选一对起始点(起点与终点不能选同一个格子,并且不能选’#’),它们之间的路径长度指的是最短的那条路径。问这些起始点对中最长的路径长度是多少?
- 输入描述
N M,N是迷宫的长度,M是迷宫的宽度
接下来是N行,M列的格子 - 输出描述
最长的路径长度 - 示例
3 3
. . .
. # .
. . .
4
5 5
. . . # .
. . . # .
. # . . .
# . . . .
. # . . #
8
5 5
# . . # .
. . . # .
. . . . .
# . # . .
. . . . #
8
解释:这三个迷宫,都是对角的点对的路径长度是最大的。
图论,遍历整个图,每次遍历从每个起点开始BFS,得到这个起点所能到达的最远终点,返回其路径。整个遍历完,得到最大路径。
def bfs(i, j):
from collections import deque
directions = {(-1, 0), (1, 0), (0, -1), (0, 1)}
visited = set()
q = deque()
q.append((i, j))
visited.add((i, j))
path = -1
while q:
path += 1
num = len(q)
for k in range(num):
x, y = q.popleft()
for direction in directions:
adj_x, adj_y = x+direction[0], y+direction[-1]
if 0 <= adj_x < N and 0 <= adj_y < M and graph[adj_x][adj_y] == '.' and (adj_x, adj_y) not in visited:
q.append((adj_x, adj_y))
visited.add((adj_x, adj_y))
return path
if __name__ == "__main__":
line = sys.stdin.readline().strip()
values = list(map(int, line.split()))
N, M = values[0], values[-1]
graph = []
for i in range(N):
data = sys.stdin.readline().strip().split()
graph.append(data)
res = 0
for i in range(N):
for j in range(M):
if graph[i][j] == '.':
max_path = bfs(i, j)
res = max(res, max_path)
print(res)
听曲子
4名室友听歌,每个人有自己的n首歌可选,每首歌有其播放时间。每个人从自己的n首歌中选歌,至少选一首,最多N首,问4个人中的最长的播放总长与最短的播放总长相差最小是多少?
- 输入描述
N,曲子数
接下来4行N列 - 输出描述
最小的最长的播放总长与最短的播放总长的差 - 示例
3
240 300 360
600 200 200
300 400 500
600 600 600
100
解释:所选方案为240+360/600/500/600,所以输出为600-500=100
暴力解法就是列出每个人的可选方案,然后计算出结果,这样的时间复杂度为 O ( 4 ∗ 2 n ) O(4*2^n) O(4∗2n),加上剪枝,可以过。。。
def gen_solution(data, tmp, idx):
solution.add(tmp)
if idx < len(data):
gen_solution(data, tmp+data[idx], idx+1)
gen_solution(data, tmp, idx+1)
if __name__ == "__main__":
N = int(sys.stdin.readline().strip())
solutions = []
for i in range(4):
line = sys.stdin.readline()
data = list(map(int, line.split()))
solution = set()
gen_solution(data, 0, 0)
solution.remove(0)
solutions.append(solution)
res = sys.maxsize
for i0 in solutions[0]:
for i1 in solutions[1]:
if abs(i0-i1) >= res:
continue
for i2 in solutions[2]:
if abs(i0-i2) >= res or abs(i1-i2) >= res:
continue
for i3 in solutions[3]:
res = min(res, max(i0, i1, i2, i3)-min(i0, i1, i2, i3))
print(res)