如何解决将正整数表示为三个数字的总和
可以用多少种方式将正整数n
表示为三个不同正整数之和。如果一个方法包含一个数字,而另一个方法则没有,那么这两种方法是不同的。
我设法获得了以下脚本,以将写n
的方式的数量计为三个数字的总和,但这并没有考虑其他条件。
def nways(n):
if (n <= 2):
return False
else:
ways = (n - 1) * (n - 2) / 2
return ways
例如,如果n = 8,则我需要返回2,因为1 + 2 + 5 = 8和1 + 3 + 4 = 8,但是当前函数返回21 ...
背后的正确算法和数学是什么?
解决方法
解决方案
def nways(n):
nways = 0
for i in range(1,n-2):
min_j,max_j = i+1,(n-i-1)//2
nways += (max_j - min_j + 1) if max_j >= min_j else 0
return nways
此算法消耗O(N)
时间和O(1)
空间。
说明
让我们将三个正数表示为i
,j
,k
。
由于它们都是不同的,因此这三个数字必须彼此大于或小于。我们假设最小的数字为i
,中间的数字为j
,最大的数字为k
。因此关系将为i < j < k
。
以n = 18
为例
- 我们从
i = 1
开始,然后j + k
应该是17
。- 因此
(j,k)
可能从(2,12)
,(3,14)
,...到(8,9)
。 - 通知
(j,k)
不能为(9,8)
,(10,7)
,因为j<k
- 因此,
min_j
将是i+1
(在这种情况下为2
),max_j
将是(n-i-1)//2
(在这种情况下为8
) -
(j,k)
组合的数量为max_j - min_j + 1
,在这种情况下为7
对
- 因此
- 我们继续
i = 2
,然后将j + k
设为16
。-
min_j
将是i+1
(在这种情况下为3
),max_j
将是(n-i-1)//2
(在这种情况下为7
) -
(j,k)
组合的数量为max_j - min_j + 1
,在这种情况下为5
对
-
我们尝试i
的所有可能值,然后将(j,k)
对的所有组合加起来,然后得出答案。
您可以使用蛮力,还有更多工作:
- 检查三个术语是否不同
- 存储一组唯一的条款
- 那套衣服的长度就是你的结果
sourcetype
演示:https://repl.it/repls/ChocolateHelplessLivecd
,一种非常不同的方法是使用约束求解器。这是一个示例:
import constraint as con
n = 8
p = con.Problem()
p.addVariables(['x','y','z'],range(1,n-2))
p.addConstraint(con.ExactSumConstraint(n))
p.addConstraint(lambda a,b,c : a < b < c,("x","y","z"))
sols = p.getSolutions()
print(len(sols))
sols
这给出了:
2
[{'x': 1,'y': 3,'z': 4},{'x': 1,'y': 2,'z': 5}]
我不知道预测溶液数量的简单公式。
,您可以对@ hgb123已经很好的答案进行一些相当重要的优化,使其仍然使用蛮力,但是要更加聪明:
def ways(n):
tuple_sum_set = set()
for i in range(1,n-2):
for j in range(i+1,n-2):
for k in range(j+1,n-2):
if i + j + k == n:
tuple_sum_set.add((i,j,k))
print(tuple_sum_set)
return len(tuple_sum_set)
(如果您对此答案进行投票,请同时对@ hgb123的投票进行投票,因为这是他的答案的衍生形式)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。