素数分解
数学题
买票
dp题
平分物品
现在有n个物品,每个物品都有一个价值,现在想将这些物品分给两个人,要求这两个人分到的物品价值总和相同(个数可以不同,总价值相同即可),剩下的物品就要扔掉,现在想知道最少需要扔多少价值的物品才能满足要求分给两个人。
- 输入描述
第一行输入n,表示物品个数
第二行输入n个物品的价值 - 输出描述
最少需要扔掉多少价值的物品 - 示例
5
30 60 5 15 30
20
解释:平分了60+30+30,丢弃了5+15,所以输出20
暴力法,时间复杂度为 O ( 3 n ) O(3^n) O(3n)
import sys
if __name__ == "__main__":
n = int(sys.stdin.readline().strip())
# 读取每一行
line = sys.stdin.readline().strip()
# 把每一行的数字分隔后转化成int列表
data = list(map(int, line.split()))
res = sys.maxsize
def dfs(idx, a, b, drop):
global res
if idx == len(data):
if a == b:
res = min(res, drop)
return
dfs(idx+1, a+data[idx], b, drop)
dfs(idx+1, a, b+data[idx], drop)
dfs(idx+1, a, b, drop+data[idx])
dfs(0, 0, 0, 0)
print(res)
dp法,时间复杂度为 O ( n ∗ t o t a l ) O(n*total) O(n∗total), t o t a l total total是所有物品价值之和
import sys
if __name__ == "__main__":
n = int(sys.stdin.readline().strip())
# 读取每一行
line = sys.stdin.readline().strip()
# 把每一行的数字分隔后转化成int列表
data = list(map(int, line.split()))
total = sum(data)
dp = [0]*(total+1)
dp[0] = 1
for i in range(n):
for j in range(total, data[i]-1, -1):
dp[j] = dp[j] | dp[j-data[i]]
res = total
for i in range(total, -1, -1):
if i % 2 != 0:
continue
if dp[i] and dp[i//2]:
res = total-i
break
print(res)
教授认可
n个教授讨论学术成果,如果教授 i i i认可教授 j j j,教授 j j j认可教授 k k k,那么可以认为教授 i i i认可教授 k k k。教授可以自己认可自己的学术成果。
- 输入描述
第一行输入n和m,表示n个教授,m条认可关系
接下来m行,每一行输入认可关系<x,y>,表示教授x认可教授y - 输出描述
输出互相认可的教授对有多少 - 示例
5 6
1 3
3 2
2 1
3 5
5 4
4 5
4
解释: 教授1,2,3互相认可,这有3对;教授4,5互相认可,这有1对。共4对。
图论之有向图寻找强连通分量,强连通分量指的是结点可以互相到达的子图。使用tarjan算法,时间复杂度为 O ( V + E ) O(V+E) O(V+E), V V V表示结点个数, E E E表示有向边个数。
from collections import defaultdict
def tarjan(node):
global dfn, low, time, stack, res
dfn[node] = low[node] = time
time += 1
stack.append(node)
for adj_node in graph[node]:
if dfn[adj_node] == 0:
tarjan(adj_node)
low[node] = min(low[node], low[adj_node])
elif adj_node in stack:
low[node] = min(low[node], low[adj_node])
count = 0
if dfn[node] == low[node]:
while stack:
tmp = stack.pop()
count += 1
if tmp == node:
break
if count > 1:
res += int((count*(count-1))/2)
if __name__ == "__main__":
# 读取每一行
line = sys.stdin.readline().strip()
# 把每一行的数字分隔后转化成int列表
nm = list(map(int, line.split()))
n, m = nm[0], nm[1]
# 构建图
time = 1
dfn = [0]*(n+1)
low = [0]*(n+1)
stack = []
graph = defaultdict(list)
for i in range(m):
# 读取每一行
line = sys.stdin.readline().strip()
# 把每一行的数字分隔后转化成int列表
xy = list(map(int, line.split()))
if xy[0] == xy[1]:
continue
graph[xy[0]].append(xy[1])
res = 0
for node in range(1, n+1):
if dfn[node] == 0:
tarjan(node)
print(res)