题目描述
题目描述
若两个正整数的和为素数,则这两个正整数称之为“素数伴侣”,如2和5、6和13,它们能应用于通信加密。现在密码学会请你设计一个程序,从已有的N(N为偶数)个正整数中挑选出若干对组成“素数伴侣”,挑选方案多种多样,例如有4个正整数:2,5,6,13,如果将5和6分为一组中只能得到一组“素数伴侣”,而将2和5、6和13编组将得到两组“素数伴侣”,能组成“素数伴侣”最多的方案称为“最佳方案”,当然密码学会希望你寻找出“最佳方案”。
输入:
有一个正偶数N(N≤100),表示待挑选的自然数的个数。后面给出具体的数字,范围为[2,30000]。
输出:
输出一个整数K,表示你求得的“最佳方案”组成“素数伴侣”的对数。
输入描述:
输入说明
1 输入一个正偶数n
2 输入n个整数
输出描述:
求得的“最佳方案”组成“素数伴侣”的对数。
思路:素数,除了2是偶数,其他是奇数——而现在不可能出现2了,所以我们只考虑奇数的素数2个数的和是奇数,有什么情况呢?只有奇数+偶数。所以,我们把这些数分成2堆——奇数和偶数,然后在他们中间,和是素数的,连上一条边,然后做匹配。因为对二分图的最大匹配,有一个简单很多的算法,匈牙利算法。二分图就是,你可以把图上的点分成2堆,每堆之内的点不会有边,2堆之间,才可能连边。换句话说,一条边,必定连2个来自不同堆的点。现在,对每条边,一定连一个奇数,一个偶数,点能按奇数和偶数分成两部分,刚好就是二分图嘛!
匈牙利算法:https://blog.youkuaiyun.com/sunny_hun/article/details/80627351
import math
def prime_judge(n):
if n>1:
m = int(math.sqrt(n))
if n % 2 == 0:#将2及所有合数因子排除掉
return False
else:
for i in range(m + 1)[3::2]:#从3起步,步长为2
if n % i == 0:
return False
return True
return False
def group_lst(lst): ##分奇偶
odd = []
even = []
for i in lst:
if int(i) % 2 == 1:
odd.append(int(i))
else:
even.append(int(i))
return (odd, even)
def matrix_ab(a, b):
matrix = [[0 for i in range(len(b))] for i in range(len(a))]
for ii, i in enumerate(a):
for jj, j in enumerate(b):
if prime_judge(i + j) == True:#和为素数,则对应索引标为1
matrix[ii][jj] = 1
return matrix
def find(x):#匈牙利算法从b中为x找匹配
for index, i in enumerate(b):#遍历b中每个元素
if matrix[x][index] == 1 and used[index] == 0:#如果有素数搭配连接并且无标记(标记的十一时这次曾试图改变归属,但没有成功)
used[index] = 1
if connect[index] == -1 or find(connect[index]) != 0:#b中元素无连接或能腾出位置
connect[index] = x#为b匹配
return 1
return 0
while True:
try:
n = int(input())
m = input().split()
(a, b) = group_lst(m)
matrix = matrix_ab(a, b)
connect = [-1 for i in range(len(b))]
count = 0
for i in range(len(a)):
used = [0 for j in range(len(b))]
if find(i):
count += 1
print(count)
except:
break