Algorithm 计算重复整数置换的模

Algorithm 计算重复整数置换的模,algorithm,modular-arithmetic,Algorithm,Modular Arithmetic,我想计算PsmodK,其中Ps是集合S中元素唯一排列的总数。问题是,集合S可能有重复,因此Ps=n!/(f1!f2!…fn!),其中n是元素数,分母是S中每个元素频率的阶乘乘积 可以假定整数n非常大,比如说大约10^6,不太可能适合uint64\t。甚至可以不借助任意精度库计算PsmodK?如果是,有什么快速的方法来计算吗?以9为例/(4!3!2!)。这是 9.8.7.6 5.4.3 2.1 ------- x ----- x --- 4.3.2.1 3.2.1 2.1 换句话

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


可以假定整数n非常大,比如说大约
10^6
,不太可能适合
uint64\t
。甚至可以不借助任意精度库计算Ps
mod
K
?如果是,有什么快速的方法来计算吗?

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
的方法:


如果要计算,例如n!modK,您不需要计算n第一。相反,你可以做一个这样的循环

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

对于(i=2;i如果需要为许多Ps的值计算Ps
mod
K
,那么明智的做法是为所有可能需要的n值预计算n!
mod
K
(如果n≤ 106那么这是合理的)

此外,如果K是素数,则可以通过将要除以的数字的“”乘以来处理除法。例如,如果K=1000000007,则可以将其乘以500000004,而不是除以2


有几种方法可以计算它,最简单的方法是计算xK-2
mod
K
(这要归功于)。然后,您还可以预先计算每个阶乘的模乘逆。然后,使用缓存值计算Ps
mod
K
非常容易。

10^6适合
uint64\u t
。或者您的意思是
n!
不适合
uint64\u\code>?是的,
n!
不适合顺便说一句,如果n大约是
10^6!
,那么Ps
mod
K在大多数情况下都是0,除非K非常大。我假设
K
也不一定是素数?问题是这个问题涉及除法。如果你知道
n!
r!
(n-r)!
是模
K
,这不会告诉您
n!/(r!*(n-r)!)
K
,因为分母可能不是模
K
整数环的可逆元素。这是一个很好的观察结果!我要读那篇文章了。我一有工作实现就会回来。@methuselmurmu祝你好运。我想这会很难-我会做一个详细的搜索o查看库是否已执行此操作。日志链接已更新: