簡體   English   中英

在代碼中放置模運算

[英]Placing of modulo operation in code

我一直在努力解決一個問題,其中解決方案歸結為計算價值

在此輸入圖像描述 (n + m-2組合m-1)。

這就是我寫的。 如果答案超出10^9+7 ,我需要打印my_answer%(10^9+7)

mod_val=10**9+7
current=[int(x) for x in raw_input().strip().split()]
m=current[0]-1
n=current[1]-1
hi,lo=max(m,n),min(m,n)
num_prod=1
den_prod=1
for each in xrange(1,lo+1):
    den_prod=den_prod*each
    num_prod=num_prod*(hi+each)
print (num_prod//den_prod)%mod_val

但是在完成所有計算之后,模運算就在底部。 有沒有辦法我可以在代碼之間的某處放置模運算,以節省計算或提高性能?

背景

事實:

(m + n)C n =(m + n)! /(n!m!)= (1 / n!)*((m + n)!/ m!)

看代碼:

第1行: den_prod=den_prod*each代表(1 / n!)

第2行: num_prod=num_prod*(hi+each)表示((m + n)!/ m!)的簡化形式。


關鍵思想是在for循環中使用模冪運算,然后對結果應用除以模運算。 除法運算變為模和逆的乘法。 最后,為了計算模逆,我們使用歐拉定理。

def mod_inv (a, b):
    return pow(a, b - 2, b)

mod_val=10**9+7
current=[int(x) for x in raw_input().strip().split()]
m=current[0]-1
n=current[1]-1

hi,lo=max(m,n),min(m,n)
num_prod=1
den_prod=1
for each in xrange(1,lo+1):
    den_prod = (den_prod*each) % mod_val
    num_prod = (num_prod*(hi+each)) % mod_val

print (num_prod * mod_inv(den_prod, mod_val)) % mod_val

性能

我為問題定了3種不同的解決方案。 定時5000組合:( 5000 C n )其中n從0到4999。

代碼1:上面的解決方案

def mod_inv (a, b):
    return pow(a, b - 2, b)

mod_val=10**9+7

hi = 5000
for lo in range(0, hi-1):

    # Code 1
    num_prod=1
    den_prod=1
    for each in xrange(1,lo+1):
        den_prod = (den_prod*each) % mod_val
        num_prod = (num_prod*(hi+each)) % mod_val

    output = (num_prod * mod_inv(den_prod, mod_val)) % mod_val
    # print output

時間1:

real    0m3.607s
user    0m3.594s
sys     0m0.011s

代碼2:您提出的解決方案

mod_val=10**9+7

hi = 5000
for lo in range(0, hi-1):

    # Code 2
    test1 = 1
    test2 = 1
    for each in xrange(1,lo+1):
        test1 = (test1*each)
        test2 = (test2*(hi+each))

    test_output = (test2 / test1) % mod_val
    # print test_output

時間2:

real    0m25.377s
user    0m25.337s
sys     0m0.027s

代碼3: scipy解決方案

from scipy.misc import comb

hi = 5000
for lo in range(0, hi-1):

    # Code 3
    c = comb(hi+lo, lo, exact=True)
    # print c

時間3:

real    0m36.700s
user    0m36.639s
sys     0m0.048s

大輸入的API - 盧卡斯定理

def mod_inv (a, b):
    return pow(a, b - 2, b)

def small_nCr (n, r, mod):
    hi = max(r, (n - r))
    lo = min(r, (n - r))
    num_prod=1
    den_prod=1
    for each in range (1, lo + 1):
        den_prod = (den_prod * each) % mod
        num_prod = (num_prod * (hi + each)) % mod
    small_c = (num_prod * mod_inv (den_prod, mod)) % mod
    return small_c

def lucas (n, r, mod):
    c = 1
    while (n > 0 or r > 0):
        ni = n % mod
        ri = r % mod
        if (ri > ni):
            return 0
        c = c * small_nCr (ni, ri, mod)
        n = n / mod
        r = r / mod
    return c

def nCr (n, r, mod):
    return lucas (n, r, mod) % mod

注意:如果模數值不是素數,則可以應用中國剩余定理。


資料來源:

模數屬性

模冪運算

模乘乘法反函數 - pow用法

盧卡斯定理

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM