我想计算 P s mod
K ,其中 P s 是集合 S 中元素的唯一排列总数。问题是,集合 S 可以重复,所以 P s = n! /(f 1 !f 2 !... f n !),其中 n 是元素的数量,而分母是 S 中每个元素的频率因子的乘积。
可以假设整数 n 非常大,例如10^6
左右,并且不太可能适合uint64_t
。是否可以在不诉诸任意精度库的情况下计算 P s mod
K ?如果是,是否有任何快速计算方法?
答案 0 :(得分:5)
以tochar
为例。这是
9!/(4!3!2!)
换句话说,它是3个二项式系数9.8.7.6 5.4.3 2.1
------- x ----- x ---
4.3.2.1 3.2.1 2.1
的乘积。通过这种方式,您始终可以将其减少为二项式系数的乘积。您需要以模9C4 x 5C3 x 2C2
为模计算这些二项式系数,并将模板K
加在一起。
因此,您需要一种有效的方法来计算模K
的二项式系数。
我不知道这对于K
有多可行,但是这里给出了一种有效计算二项式系数mod n == 10^6
的方法:
答案 1 :(得分:0)
如果你想计算,例如 n!modK ,您不需要先计算 n!。相反,你可以做一个看起来像这样的循环。
result = 1
for(i = 2; i <= n; i++) {
result = (result * i) % K
}
解释其原因的最简单方法是查看数字的最后一位数字与其他数字相乘时会发生什么。 例如1234 * 3.结果的最后一位数是多少?它是一个等于(4 * 3)mod10的2。结果的最后一位仅受两个因子的最后一位数的影响。在每个数字系统中都是如此。不仅仅是基数10.因此,变量结果足以将结果的最后一位数存储在基数 K 中。
答案 2 :(得分:0)
如果需要为许多 P s 值计算 P s mod
K >,那么预先计算 n可能是明智的选择!对于您可能需要的所有 n 值,使用mod
K (如果 n ≤10 6 则是合理的)
此外,如果 K 是质数,则可以通过除以要除以的数字的“ modular multiplicative inverse”来处理除法。例如,如果 K = 1,000,000,007,那么您可以乘以500,000,004而不是除以2。
有几种计算方法,最简单的方法是计算 x K-2 mod
K (感谢{{3 }}。然后,您还可以预先计算每个阶乘的模乘逆。然后,使用缓存的值计算 P s mod
K 非常容易。