数论--Lucas Theorem

来源:互联网 发布:linux http proxy 编辑:程序博客网 时间:2024/06/05 17:13

此定理用来求 (nm) mod p. ( p 是素数 )
适用:大的组合数取模。

定理给出: (nm)mod  p =(n/pm/p) * (n%pm%p) mod p

详细证明参见 Wikipedia: Lucas’ theorem

代码实现(hdoj–3037):

#include <iostream>#include <cmath>#include <algorithm>using namespace std;// 1856MS 2584Ktypedef long long ll;const int maxn = 100010;ll  f[maxn];int t, n, m, p;void init(ll p){    f[0] = 1;    for(int i = 1; i <= p; ++i) f[i] = f[i - 1] * i % p;}//求逆元ll inv(ll a, ll m){    if(a == 1) return 1;    return inv(m % a, m) * (m - m / a) % m;}ll pow(ll a, ll b, ll p){    ll res = 1;    while(b){        if(b & 1) res = res * a % p;        a = a * a % p;        b >>= 1;    }    return res;}ll Lucas(ll n, ll m, ll p){    ll ans = 1;    while( n && m )    {        ll a = n % p;        ll b = m % p;        if(a < b) return 0;        //两者皆可        //ans = (ans * f[a] % p) * inv(f[b] * f[a - b] % p, p) % p;        ans = ans * f[a] * pow(f[b] * f[a - b] % p, p - 2, p) % p;        n /= p;        m /= p;    }    return ans;}int main(){    for(cin >> t; t--; ){        cin >> n >> m >> p;        init(p);        cout << Lucas(n + m, m, p) << endl;    }    return 0;}
0 0
原创粉丝点击