模块化算术:除以阶乘数%Prime

时间:2014-01-18 07:22:47

标签: java python algorithm modular-arithmetic

我想有效地计算((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的解决方案或任何标准算法/库用于取消因子(如果反向选项不是完全证明)或接近此类问题。

3 个答案:

答案 0 :(得分:3)

((X+Y)!/(X!Y!))是拼写二项式系数((X+Y)-choose-X)的低级方式。虽然你在问题中没有这样说,但代码中的注释意味着P是素数。将这两者放在一起,卢卡斯定理直接适用:http://en.wikipedia.org/wiki/Lucas%27_theorem

这提供了一个非常简单的算法,该算法基于PX+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),则代码将更加简单。

http://en.wikipedia.org/wiki/Combination

答案 2 :(得分:3)

您需要的是一种有效的方法: -

  
      
  1. C(n,k)= C(n-1,k)+ C(n-1,k-1)

  2.   
  3. 使用动态编程来计算自下而上方法的效率

  4.   
  5. 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

  6.   

另一种更快的方法: -

  
      
  1. C(n,k)= C(n-1,k-1)* n / k

  2.   
  3. F(n,k)=((F(n-1,k-1)* n)%P * inv(k)%P)%P

  4.         

    inv(k)%P表示k的模逆。

注意: - 尝试评估C(n,n-k) if (n-k<k) because nC(n-k) = nCk