【发布时间】:2011-06-13 01:12:07
【问题描述】:
有没有一种有效的算法来计算最小整数 N,使得 N!可被 p^k 整除,其中 p 是一个相对较小的素数,k 是一个非常大的整数。换句话说,
factorial(N) mod p^k == 0
如果给定 N 和 p,我想知道 p 被 N 整除多少次!我会使用众所周知的公式
k = Sum(floor(N/p^i) for i=1,2,...
我已经对较小的 k 值进行了蛮力搜索,但是随着 k 的增加,这种方法很快就会失效,而且似乎没有可以推断出更大值的模式。
于 2011 年 6 月 13 日编辑
使用 Fiver 和 Hammar 提出的建议,我使用准二元搜索来解决问题,但并不完全按照他们建议的方式。使用上面第二个公式的截断版本,我将 N 的上限计算为 k 和 p 的乘积(仅使用第一项)。我使用 1 作为下限。使用经典的二分搜索算法,我计算了这两个值之间的中点,并计算了在第二个公式中使用这个中点值作为 N 的 k 值,这次使用了所有术语。
如果计算的 k 太小,我调整下限并重复。太大了,我首先测试了在 midpoint-1 计算的 k 是否小于所需的 k。如果是,则返回中点作为最接近的 N。否则,我调整高点并重复。
如果计算出的 k 相等,我测试 midpoint-1 的值是否等于中点的值。如果是这样,我将高点调整为中点并重复。如果 midpoint-1 小于所需的 k,则返回中点作为所需的答案。
即使 k 值非常大(10 位或更多位),这种方法也能以 O(n log(n)) 的速度运行。
【问题讨论】:
-
虽然 Nemo 的回答不是很清楚,但我相信它比二分查找要好。毕竟,它是 O(1)!或者,更准确地说,因为您必须处理数字,所以它是 O(log k)。这个问题是直接可以解决的,所以不需要做一些迭代计算。
-
最好将答案放入您自己问题的答案中,而不是作为对问题的编辑。
-
“10 位或更多位”不是“非常大”:-)。我已经编辑了答案以添加 Perl 实现。即使对于几十位数字的 k 似乎也可以正常工作,尽管我不知道答案是否正确。如果你能找到给出错误答案的案例,我想看看。
-
你应该发布你的编辑作为答案,因为它是一个。