Algorithm 求所有商之和

Algorithm 求所有商之和,algorithm,math,Algorithm,Math,给定两个数M和N。设qi为i*N/M的整数部分。从0到M-1,qi在i上的和是多少。O(M)是显而易见的方法。这能在更短的时间内完成吗,可能是O(1),如果存在一些更简单的简化表达式?在我看来,你是在尝试求和0N/M+1N/M+2N/M+3N/M。。。(M-1)N/M。如果是这样,你有(0+1+2+3…+(M-1))N/M。你可以在O(1)中求解,因为(0+1+2+3+…+(M-1))是M*(M-1)/2。M被取消,你得到(M-1)N/2。有趣的问题。(这篇文章会让我希望我们有数学格式,所以…)

给定两个数M和N。设qi为i*N/M的整数部分。从0到M-1,qi在i上的和是多少。O(M)是显而易见的方法。这能在更短的时间内完成吗,可能是O(1),如果存在一些更简单的简化表达式?

在我看来,你是在尝试求和0N/M+1N/M+2N/M+3N/M。。。(M-1)N/M。如果是这样,你有(0+1+2+3…+(M-1))N/M。你可以在O(1)中求解,因为(0+1+2+3+…+(M-1))是M*(M-1)/2。M被取消,你得到(M-1)N/2。

有趣的问题。(这篇文章会让我希望我们有数学格式,所以…)

我的方法是将问题写为

∑i floor(i*N/M) = ∑i i*N/M - ∑i [i*N/M]
其中,
[]
是运算符的“小数部分”(即[1.3]=0.3,[6]=0等)

然后,前半部分很简单:它是一个普通的算术序列和乘以
N/M
,因此它和
N*(M-1)/2
。下半场更难对付,但你会明白为什么把它和上半场分开是至关重要的

k=gcd(N,M)
。然后,让
n=n/k
m=m/k
,那么后半部分是
∑i[i*n/m]
。关键的是,
n
m
现在是相对优质的。
i
的总和是从
0
M-1=km-1
。我们可以将
i
拆分为
m
的倍数和余数,如
i=qm+r
,因此现在求和

∑q ∑r [r*n/m]
其中,
q
和从
0
k-1
r
和从
0
m-1
。现在是关键步骤:因为
n
m
是相对素数,
r=0..m-1的序列
r*n
0,1,2,3,…,m-1
mod m的排列。因此,序列
[r*n/m]
0/m、1/m、2/m、…(m-1)/m
的排列,因此
∑r[r*n/m]=∑r/m=m*(m-1)/2/m=(m-1)/2
。因此,整个总和崩溃为
k*(m-1)/2=(km-k)/2=(m-k)/2

最后,我们将两半结合起来:
N*(M-1)/2-(M-k)/2=(NM-N-M+k)/2


因此,期望的和是
(NM-N-M+gcd(N,M))/2
。可以使用欧几里德算法计算GCD,因此计算速度相当快。

如果是商或i*N/M的整数部分,你会对这个问题有更好的回答。商可能有误导性。我编辑。