计算小于n且能被3或5整除的数的总和时结果异常,请求排查与优化
计算小于n且能被3或5整除的数的总和时结果异常,请求排查与优化
嗨,我帮你找到问题啦!你的代码里犯了一个经典的重复计算错误:那些同时能被3和5整除的数(也就是能被15整除的数,比如15、30、45...),既在被5整除的循环里加了一次,又在被3整除的循环里加了一次,相当于被算了两遍,这就是n=100时结果偏大的原因。
为什么n=10的时候没问题呢?因为小于10的数里,同时被3和5整除的只有0,加两次0对总和没影响,所以结果是对的;但n=100时,15、30...90这些数都被重复加了,总和自然就多出来了(多出来的部分就是这些15倍数的总和:15+30+...+90=315,2633-315=2318,正好是正确结果)。
先看看你的原始代码问题点:
#!/bin/python3 import sys import math arr = [] sum1 = 0 sum2 = 0 t = int(input().strip()) while t < 1 or t > 10**5: print() t = int(input().strip()) for i in range(t): n = int(input().strip()) arr.append(n) for x in range (0, len(arr)): sum1 = 0 sum2 = 0 for b5 in range (0, arr[x], 5): sum1 = sum1 + b5 for b3 in range (0, arr[x], 3): sum2 = sum2 + b3 sum = sum1 + sum2 print(sum)
解决方案1:修正重复计算问题(循环版)
你后来加的if语句思路是对的,就是把重复加的数减掉,不过可以稍微调整得更清晰一点:
for x in range (0, len(arr)): total = 0 # 先加所有能被3整除的数 for b3 in range (3, arr[x], 3): total += b3 # 再加那些能被5整除但不能被3整除的数 for b5 in range (5, arr[x], 5): if b5 % 3 != 0: total += b5 print(total)
(这里我把起始值改成了3和5,因为0加不加不影响总和,还能少一次循环)
解决方案2:用数学公式优化(高效版)
如果输入的t很大(比如题目要求的1e5次),循环的效率会很低,这时候用数学公式计算会快很多。
计算小于n的数中,能被k整除的数的总和公式是:总和 = k * m * (m + 1) // 2
其中m是小于n的最大k的倍数的项数,也就是m = (n - 1) // k
根据这个公式,我们可以直接算出:
- 能被3整除的数的总和
- 能被5整除的数的总和
- 能被15整除的数的总和(因为这部分被重复计算了,要减掉一次)
最终总和就是sum3 + sum5 - sum15,代码如下:
#!/bin/python3 def get_divisible_sum(n, k): m = (n - 1) // k return k * m * (m + 1) // 2 t = int(input().strip()) while t < 1 or t > 10**5: print() t = int(input().strip()) for _ in range(t): n = int(input().strip()) sum3 = get_divisible_sum(n, 3) sum5 = get_divisible_sum(n, 5) sum15 = get_divisible_sum(n, 15) print(sum3 + sum5 - sum15)
这个版本不管n多大,都能瞬间算出结果,完全不用担心性能问题。
你后来自己修改的思路是对的,已经抓到了重复计算的核心问题,只是可以进一步优化代码的简洁性和效率哦!
备注:内容来源于stack exchange,提问作者Pascal Barthelmäs
相关产品推荐
相关产品推荐

