关于模运算的行为?

时间:2014-02-04 13:59:29

标签: python modulus

我在python中为以下codechef问题http://www.codechef.com/problems/MOVES/

编写了以下程序
import sys

tokenizedInput = sys.stdin.read().split()
mod=1000000007
arr=[1]*5001
for i in range(1,5001):
    arr[i]=(arr[i-1]*i)%mod

def combo(r,n,mod):
    q=arr[n]
    print q
    r=(arr[r]*arr[n-r])
    print r
    return ((q/r)%mod)

elm=0

for i in range (0,5001):
    n=int(tokenizedInput[elm])
    elm=elm+1
    k=int(tokenizedInput[elm])
    elm=elm+1
    if(n==0 and k==0):
        break
    out=0
    if(((k-1)/2)!=(k/2)):
      out=(2*combo((k-1)/2,n-2,mod)*combo(k/2,n-2,mod))%mod
    else:
      out=(2*combo(k/2,n-2,mod)**2)%mod
    print out

但我的模数函数无法正常工作,例如值n = 498 并且r = 2,combo()返回的答案为0,因为q = 243293343,r = 1428355228 如何在arr []中执行我的模运算来纠正这个错误?

3 个答案:

答案 0 :(得分:1)

上述幂函数通过使用平方所谓的取幂来计算O(log(b))中的^ b。这个想法非常简单:

       (a^2)^(b/2)          if b is even and b > 0
a^b =  a*(a^2)^((b-1)/2)    if b is odd
        1                  if b = 0

这个想法可以很容易地实现,如下所示:

/* This function calculates (a^b)%c */
int modulo(int a,int b,int c)
{
    long long x=1,y=a; 
    while(b > 0)
    {
        if(b%2 == 1)
        {
            x=(x*y)%c;
        }
        y = (y*y)%c; // squaring the base
        b /= 2;
    }
    return x%c;
}

上述幂函数只是一种递归方式。 当你问起这个

  

但如果有人解释使用return(base * Power(base,expo-1)%mod)背后的数学,那将会有很大的帮助

这与检查expo是否为奇数然后将base与base ^(expo-1)相乘以使新的expo即(expo-1)变为偶数并重复平方可以完成相同

有关详细信息,请参阅:

Topcoder Tutorial

wiki: expo by squaring

答案 1 :(得分:0)

获得解决方案,回答我自己的问题,但鼓励搜索优化版本 错误是

  

return((q / r)%mod)

对于mod为1000000007(即素数),

是错误的,它必须写为

  

R =(ARR [R] * ARR [N-R])%模

     

return(q * Power(r,mod-2))%mod

电源功能

def Power(base,expo):
if(expo==0):
  return 1
else:
    if(expo&1):
      return(base*Power(base,expo-1)%mod)
    else:
      root=Power(base,expo>>1)
      return(root*root%mod) 

但如果有人解释使用return(base * Power(base,expo-1)%mod)背后的数学,那将会有很大的帮助

答案 2 :(得分:0)

当我们分割(a / b)%MOD时,我们会做这样的事情。

(A / B)%MOD

(a * inverse(b))%MOD //你必须找到b的倒数。要找到b的倒数,请使用费马定理。

注意永远不要将a / b除以然后取MOD,首先找到b的倒数然后做一个* b然后修改它。