Algorithm 求所有商之和
给定两个数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。有趣的问题。(这篇文章会让我希望我们有数学格式,所以…) 我的方法是将问题写为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。有趣的问题。(这篇文章会让我希望我们有数学格式,所以…)
∑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的整数部分,你会对这个问题有更好的回答。商可能有误导性。我编辑。