簡體   English   中英

當n非常大時,有效地計算nCr mod p

[英]Calculating nCr mod p efficiently when n is very large

我需要有效地計算nCr mod p 現在,我已經編寫了這段代碼,但它超出了時間限制。 請建議更優化的解決方案。

對於我的情況, p = 10^9 + 7 and 1 ≤ n ≤ 100000000

我還必須確保沒有溢出,因為nCr mod p保證適合32位整數,但是n! 可能會超出限制。

def nCr(n,k):
    r = min(n-k,k)
    k = max(n-k,k)
    res = 1
    mod = 10**9 + 7

    for i in range(k+1,n+1):
        res = res * i
        if res > mod:
            res = res % mod

    res = res % mod
    for i in range(1,r+1):
        res = res/i
    return res

PS:我認為我的代碼可能不完全正確。 但是,它似乎適用於小n 如果錯了,請指出來!

來自http://apps.topcoder.com/wiki/display/tc/SRM+467

long modPow(long a, long x, long p) {
    //calculates a^x mod p in logarithmic time.
    long res = 1;
    while(x > 0) {
        if( x % 2 != 0) {
            res = (res * a) % p;
        }
        a = (a * a) % p;
        x /= 2;
    }
    return res;
}

long modInverse(long a, long p) {
    //calculates the modular multiplicative of a mod m.
    //(assuming p is prime).
    return modPow(a, p-2, p);
}
long modBinomial(long n, long k, long p) {
// calculates C(n,k) mod p (assuming p is prime).

    long numerator = 1; // n * (n-1) * ... * (n-k+1)
    for (int i=0; i<k; i++) {
        numerator = (numerator * (n-i) ) % p;
    }

    long denominator = 1; // k!
    for (int i=1; i<=k; i++) {
        denominator = (denominator * i) % p;
    }

    // numerator / denominator mod p.
    return ( numerator* modInverse(denominator,p) ) % p;
}

請注意,我們使用modpow(a,p-2,p)來計算mod逆。 這與Fermat的小定理一致,該定理指出(a ^(p-1)與1個模p一致)其中p是素數。 因此,它暗示(a ^(p-2)與^( - 1)模p)一致。

C ++到Python的轉換應該很容易:)

關於最后一個問題:我認為你的代碼中的錯誤是計算產品,將其減去模k ,然后將結果除以r! 這與減少模k之前的除法不同。 例如, 3*4 / 2 (mod 10) != 3*4 (mod 10) / 2

暫無
暫無

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

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