【问题标题】:Calculate modulo of permutations of repeated integers计算重复整数排列的模
【发布时间】:2015-10-03 22:27:52
【问题描述】:

我想计算 PsmodK 其中 Ps 是总数S 集合中元素的唯一排列。问题是,集合 S 可以有重复,所以 Ps = n! / (f1!f2! ... fn!),其中 n是元素的个数,分母是S中每个元素的频率阶乘的乘积。

可以假设整数 n 非常大,比如在10^6 附近,并且不太可能适合uint64_t。甚至可以在不借助任意精度库的情况下计算 PsmodK 吗?如果有,有什么快速的计算方法吗?

【问题讨论】:

  • 顺便说一下,10^6 适合 uint64_t
  • 或者您的意思是n! 不适合uint64_t
  • 是的,n! 不适合。
  • 顺便说一句。如果 n 在 10^6! 附近,则 Ps mod K 在大多数情况下将为 0,除非 K 非常大。
  • 我认为k 也不一定是素数?

标签: algorithm modular-arithmetic


【解决方案1】:

9!/(4!3!2!) 为例。这是

9.8.7.6   5.4.3   2.1
------- x ----- x ---
4.3.2.1   3.2.1   2.1

换句话说,它是 3 个二项式系数 9C4 x 5C3 x 2C2 的乘积。通过这种方式,您总是能够将其减少为二项式系数的乘积。您需要计算出这些二项式系数以 K 为模,然后将答案以 K 为模相乘。

因此,您需要一种有效的方法来计算以 K 为模的二项式系数。

我不知道这对n == 10^6 有多可行,但这里给出了一种有效计算二项式系数 mod K 的方法:

https://fishi.devtail.io/weblog/2015/06/25/computing-large-binomial-coefficients-modulo-prime-non-prime/

【讨论】:

  • 这是一个巧妙的观察!我要去读那篇文章。一旦我有一个可行的实现,我会尽快回来。
  • @MethusaelMurmu 祝你好运。我认为这将非常困难 - 我会进行详细搜索,看看图书馆是否已经这样做了。
  • 博客链接已更新:fishi.devtail.io/weblog/2015/06/25/…
【解决方案2】:

如果你想计算例如n!modK,您不需要先计算 n!。相反,您可以执行如下所示的循环。

result = 1
for(i = 2; i <= n; i++) {
  result = (result * i) % K
}

解释为什么这样有效的最简单方法是查看当您将数字与其他数字相乘时,数字的最后一位发生了什么变化。 例如1234 * 3. 结果的最后一位数是多少?这是一个 2,等于 (4*3)mod10。结果的最后一位仅受两个因素的最后一位影响。在每个数字系统中都是如此。不只是以 10 为基数。因此,变量 result 将结果的最后一位存储在基数 K 中就足够了。

【讨论】:

  • 问题是问题涉及除法。如果您知道n!r!(n - r)! 是模K,那并不能告诉您n!/(r! * (n - r)!)K 的值,因为分母可能不是环的可逆元素整数模 K.
【解决方案3】:

如果需要为 Ps 的许多值计算 PsmodK,那么预先计算 n! modK 表示您可能需要的所有 n 值(如果 n ≤ 106 那么这是合理的)。

此外,如果 K 是素数,您可以通过乘以要除以的数字的“modular multiplicative inverse”来处理除法。例如,如果 K=1,000,000,007,那么您可以乘以 500,000,004,而不是除以 2。

有几种计算方法,最简单的一种是计算 xK-2modK(感谢Fermat's little theorem)。然后,您也可以预先计算每个阶乘的模乘逆。然后使用缓存的值很容易计算 PsmodK

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-04
    • 1970-01-01
    • 2015-12-07
    • 1970-01-01
    相关资源
    最近更新 更多