找到会给你最大和的数字子集
Finding a subset of numbers that will give you the max sum
如何找到从 2 到 1000 的数字子集,在子集中的任何两个数字不共享质因数(例如,1000 和 500 共享质因数)的情况下,该子集将为您提供最大和2)?
上述问题的一个(可能更简单)变体:子集中最大的数是多少?我们知道997是素数,很容易排除1000和998,那么问题就变成了999是否在子集中?
创建一个包含节点 {2, ..., 1000} 和当节点 gcd > 1 时的边的图。此问题的解决方案与查找 maximum-weight independent set problem, which is NP-hard except in some special cases. This graph case doesn't look like a spacial case from list on Wikipedia page or even on this list.
相同
更新
正如 James 所建议的那样,可以减少此图中的节点数量。假设具有素数分解 p1^k1*...*pn^kn
的数字 N 的签名是一个元组 (p1, ..., pn)
.
第一个归约是当存在具有更大值和相同签名的节点时删除节点。这将图形减少到 607 个节点。
如果有节点的签名是 (p1, ..., pn)
的分解并且总和是 >= N
,则下一个缩减是删除节点 N
和签名 (p1, ..., pn)
。这将图形减少到 277 个节点。
这些节点中有 73 个是孤立节点(素数 > 500。)
我不知道这个问题的答案,这对我来说似乎很重要。这里有一些想法。
总和由可变数量的被加数组成,比如 s0 + s1 + ... sk,其中si为区间[2, 1000]内的整数。现在每个 si 都有素数幂分解 si=(p1e1)*(p2e2) ... 其中 ei ≥ 1.
条件"that any two numbers from the subset don't share common prime factors"等价于说明si成对互质,即gcd(si , sj)=1 因为 i ≠ j。同样等价地,每当一个加数 si 包含质数 p 时,这意味着没有其他加数可能包含该质数。
那么如何将质数排列成被加数呢?一个简单的规则是显而易见的。 [500, 1000] 中的所有质数只能作为单独的被加数单独出现在总和中。如果将它们乘以任何其他值,即使是最小的素数 2,乘积也会太大。这样就留下了安排较小素数的任务。我不知道他们这样做的最佳方式。为了完整起见,我将提供以下显示一种方法的简短 python 程序。
def sieve_prime_set(n):
# sieve[i] = set(p1, p2, ...pn) for each prime p_i that divides i.
sieve = [set() for i in range(n + 1)]
primes = []
next_prime = 1
while True:
# find the next prime
for i in range(next_prime + 1, len(sieve)):
if not sieve[i]:
next_prime = i
break
else:
break
primes.append(next_prime)
# sieve out by this prime
for kp in range(next_prime, n + 1, next_prime):
sieve[kp].add(next_prime)
return sieve, primes
def max_sum_strategy1(sieve):
last = len(sieve) - 1
summands = [last]
max_sum = last
prime_set = sieve[last]
while last >= 2:
last -= 1
if not sieve[last] & prime_set:
max_sum += last
prime_set |= sieve[last]
summands.append(last)
return max_sum, summands, prime_set
def max_sum_strategy2(primes, n):
return sum(p ** int(log(n, p)) for p in primes)
if __name__ == '__main__':
sieve, primes = sieve_prime_set(1000)
max_sum, _, _ = max_sum_strategy1(sieve)
print(max_sum)
print(max_sum_strategy2(primes, 1000))
输出是
84972
81447
表明 "strategy 1" 更胜一筹。
优秀,但不一定是最佳的。例如,包含 1000 似乎不错,但它迫使我们排除所有其他偶数加数和每个可被 5 整除的加数。如果我们将 1000 排除在外但包含 998,我们将使用另一个包含 5 的素数分解。但是包括 998 会强制排除其他加数。因此,最大化总和并非易事。
这里有一个 Python 脚本来解决这个问题。在我的笔记本电脑上 运行 需要几分钟。
import math
import networkx as nx
max_number = 1000
G = nx.Graph()
for i in range(2, max_number + 1):
G.add_node(i, weight=i)
for i in range(2, max_number + 1):
for j in range(i+1, max_number + 1):
if math.gcd(i, j) == 1:
G.add_edge(i, j)
numbers, sum_of_numbers = nx.max_weight_clique(G)
print(sorted(numbers))
print(sum_of_numbers)
返回的号码列表如下所示;总数是 85684。(可能还有其他有效的数字集给出了这个总数。)
[41, 59, 67, 71, 79, 83, 97, 101, 103, 107, 113, 127, 131, 137, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 841, 853, 857, 859, 863, 877, 881, 883, 887, 893, 901, 907, 911, 919, 925, 929, 937, 941, 947, 949, 953, 961, 967, 971, 973, 976, 977, 979, 981, 983, 989, 991, 997]
如何找到从 2 到 1000 的数字子集,在子集中的任何两个数字不共享质因数(例如,1000 和 500 共享质因数)的情况下,该子集将为您提供最大和2)?
上述问题的一个(可能更简单)变体:子集中最大的数是多少?我们知道997是素数,很容易排除1000和998,那么问题就变成了999是否在子集中?
创建一个包含节点 {2, ..., 1000} 和当节点 gcd > 1 时的边的图。此问题的解决方案与查找 maximum-weight independent set problem, which is NP-hard except in some special cases. This graph case doesn't look like a spacial case from list on Wikipedia page or even on this list.
相同更新
正如 James 所建议的那样,可以减少此图中的节点数量。假设具有素数分解 p1^k1*...*pn^kn
的数字 N 的签名是一个元组 (p1, ..., pn)
.
第一个归约是当存在具有更大值和相同签名的节点时删除节点。这将图形减少到 607 个节点。
如果有节点的签名是 (p1, ..., pn)
的分解并且总和是 >= N
,则下一个缩减是删除节点 N
和签名 (p1, ..., pn)
。这将图形减少到 277 个节点。
这些节点中有 73 个是孤立节点(素数 > 500。)
我不知道这个问题的答案,这对我来说似乎很重要。这里有一些想法。
总和由可变数量的被加数组成,比如 s0 + s1 + ... sk,其中si为区间[2, 1000]内的整数。现在每个 si 都有素数幂分解 si=(p1e1)*(p2e2) ... 其中 ei ≥ 1.
条件"that any two numbers from the subset don't share common prime factors"等价于说明si成对互质,即gcd(si , sj)=1 因为 i ≠ j。同样等价地,每当一个加数 si 包含质数 p 时,这意味着没有其他加数可能包含该质数。
那么如何将质数排列成被加数呢?一个简单的规则是显而易见的。 [500, 1000] 中的所有质数只能作为单独的被加数单独出现在总和中。如果将它们乘以任何其他值,即使是最小的素数 2,乘积也会太大。这样就留下了安排较小素数的任务。我不知道他们这样做的最佳方式。为了完整起见,我将提供以下显示一种方法的简短 python 程序。
def sieve_prime_set(n):
# sieve[i] = set(p1, p2, ...pn) for each prime p_i that divides i.
sieve = [set() for i in range(n + 1)]
primes = []
next_prime = 1
while True:
# find the next prime
for i in range(next_prime + 1, len(sieve)):
if not sieve[i]:
next_prime = i
break
else:
break
primes.append(next_prime)
# sieve out by this prime
for kp in range(next_prime, n + 1, next_prime):
sieve[kp].add(next_prime)
return sieve, primes
def max_sum_strategy1(sieve):
last = len(sieve) - 1
summands = [last]
max_sum = last
prime_set = sieve[last]
while last >= 2:
last -= 1
if not sieve[last] & prime_set:
max_sum += last
prime_set |= sieve[last]
summands.append(last)
return max_sum, summands, prime_set
def max_sum_strategy2(primes, n):
return sum(p ** int(log(n, p)) for p in primes)
if __name__ == '__main__':
sieve, primes = sieve_prime_set(1000)
max_sum, _, _ = max_sum_strategy1(sieve)
print(max_sum)
print(max_sum_strategy2(primes, 1000))
输出是
84972
81447
表明 "strategy 1" 更胜一筹。
优秀,但不一定是最佳的。例如,包含 1000 似乎不错,但它迫使我们排除所有其他偶数加数和每个可被 5 整除的加数。如果我们将 1000 排除在外但包含 998,我们将使用另一个包含 5 的素数分解。但是包括 998 会强制排除其他加数。因此,最大化总和并非易事。
这里有一个 Python 脚本来解决这个问题。在我的笔记本电脑上 运行 需要几分钟。
import math
import networkx as nx
max_number = 1000
G = nx.Graph()
for i in range(2, max_number + 1):
G.add_node(i, weight=i)
for i in range(2, max_number + 1):
for j in range(i+1, max_number + 1):
if math.gcd(i, j) == 1:
G.add_edge(i, j)
numbers, sum_of_numbers = nx.max_weight_clique(G)
print(sorted(numbers))
print(sum_of_numbers)
返回的号码列表如下所示;总数是 85684。(可能还有其他有效的数字集给出了这个总数。)
[41, 59, 67, 71, 79, 83, 97, 101, 103, 107, 113, 127, 131, 137, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 841, 853, 857, 859, 863, 877, 881, 883, 887, 893, 901, 907, 911, 919, 925, 929, 937, 941, 947, 949, 953, 961, 967, 971, 973, 976, 977, 979, 981, 983, 989, 991, 997]