数论——组合(Lucas定理)
题目描述
给出组合数 C(n,m) 表示从 n 个元素中选出 m 个元素的方案数。例如C(5,2)=10,C(4,2)=6。可是当 n,m 比较大的时候,C(n,m) 很大。于是 xiaobo 希望你输出 C(n,m) mod p 的值。
输入描述
输入数据第一行是一个正整数 T,表示数据组数;
接下来是 T 组数据,每组数据有 3 个正整数 n,m,p。
输出描述
对于每组数据,输出一个正整数,表示 C(n,m) mod p 的结果。
示例
输入
2
5 2 3
5 2 61
输出
1
10
备注
对于所有数据,T ≤ 100,1 ≤ m ≤ n ≤ 109,m ≤ 104,m < p < 109,p 是素数。
Lucas 定理
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod;
ll quickpower(ll b,ll p)
{
ll result=1;
while(p){
if(p&1){
result=result*b%mod;
}
p>>=1;
b=b*b%mod;
}
return result;
}
ll C(ll n,ll m)
{
if(n<m){
return 0;
}
ll a=1,b=1;
for(int i=0;i<m;i++){
a=a*(n-i)%mod;
b=b*(i+1)%mod;
}
return a*quickpower(b,mod-2)%mod;
}
ll lucas(ll n,ll m)
{
if(m==0){
return 1;
}
return lucas(n/mod,m/mod)*C(n%mod,m%mod)%mod;
}
int main()
{
int t;
ll n,m;
cin>>t;
while(t--){
cin>>n>>m>>mod;
cout<<lucas(n,m)<<endl;
}
return 0;
}