此定理用来求
(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 2584K
typedef 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;
}