我想有效地计算((X + Y)!/(X!Y!))%P(P如10 ^ 9 + 7)
这个discussion提供了一些关于分配modulo over division的见解。 我担心的是,对于一个数字,不一定存在模块化逆。 基本上,我正在寻找解决问题的代码实现。
对于乘法,它非常简单:
public static int mod_mul(int Z,int X,int Y,int P)
{
// Z=(X+Y) the factorial we need to calculate, P is the prime
long result = 1;
while(Z>1)
{
result = (result*Z)%P
Z--;
}
return result;
}
我也意识到许多因素可以在除法中取消(在取模数之前),但如果除数的数量增加,那么我发现很难有效地提出一种算法来划分。 (循环列表(因子(X)+因子(Y)...)以查看哪个除以分子的当前乘数因子。)
编辑:我不想使用BigInt解决方案。
是否有任何基于java / python的解决方案或任何标准算法/库用于取消因子(如果反向选项不是完全证明)或接近此类问题。
答案 0 :(得分:3)
((X+Y)!/(X!Y!))
是拼写二项式系数((X+Y)-choose-X
)的低级方式。虽然你在问题中没有这样说,但代码中的注释意味着P
是素数。将这两者放在一起,卢卡斯定理直接适用:http://en.wikipedia.org/wiki/Lucas%27_theorem。
这提供了一个非常简单的算法,该算法基于P
和X+Y
的基础 - X
表示。是否需要BigInts
是不可能的,因为你没有对你的论点给出任何界限,除了它们int
之外。请注意,如果mod_mul
大于最大P
的平方根(因为int
可能会溢出),那么您的示例result * Z
代码可能根本不起作用。
答案 1 :(得分:3)
这是二项式系数 - C(x+y,x)
。
您可以用不同的方式计算C(n,m)=C(n-1,m)+C(n-1,m-1)
。
如果时间复杂度为O(x * y),则代码将更加简单。
答案 2 :(得分:3)
您需要的是一种有效的方法: -
C(n,k)= C(n-1,k)+ C(n-1,k-1)
使用动态编程来计算自下而上方法的效率
- 醇>
C(n,k)%P =((C(n-1,k))%P +(C(n-1,k-1))%P)%P
因此F(n,k)=(F(n-1,k)+ F(n-1,k-1))%P
另一种更快的方法: -
C(n,k)= C(n-1,k-1)* n / k
- 醇>
F(n,k)=((F(n-1,k-1)* n)%P * inv(k)%P)%P
inv(k)%P表示k的模逆。
注意: - 尝试评估C(n,n-k) if (n-k<k) because nC(n-k) = nCk