前言:
写上一个题的时候用到组合数了,就去百度了下,在此更新一下。
typedef long long LL;
const LL md = 1e9 + 7;
const int maxn = 1e5 + 10;
LL ar[maxn],sum[maxn];
const int N = 100007;
LL f[N];
LL quickpow(LL a,LL b,LL m){
LL ans=1;
while (b!=0){
if (b%2==1){
ans=ans*a%m;
b--;
}
a=a*a%m;
b=b/2;
}
return ans;
}
//数据范围较小的组合数
LL yes(LL n,LL m){
if (n<m){
return 0;
}
if (m>n-m){
m=n-m;
}
LL s1=1,s2=1;
LL i;
for (i=1;i<=m;i++){
s1=s1*(n-i+1)%md;
s2=s2*i%md;
}
return s1*quickpow(s2,md-2,md)%md;
}
LL lucas(LL n,LL m){
if (m==0){
return 1;
}
return (lucas(n/md,m/md)*yes(n%md,m%md)%md);
}
HDU3037:传送门
//一般p在1e6以下
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <vector>
#include <algorithm>
#include <string>
#include <cmath>
#include <sstream>
using namespace std;
typedef long long LL;
int p;
inline void read(int &x){
x = 0; char ch = getchar(), c = ch;
while(ch < '0' || ch > '9') c = ch, ch = getchar();
while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
if(c == '-') x = -x;
}
inline LL exp_mod(LL a,int b){
LL ret=1;
while(b){
if(b&1){
ret=ret*a%p;
}
a=a*a%p;
b>>=1;
}
return ret;
}
LL comb(int n, int m){
if(m==0)return 1;
LL x=1, y=1;
m=min(m,n-m);
for(int i=0;i<m;++i){
x=x*(n-i)%p;
y=y*(m-i)%p;
}
return x*exp_mod(y,p-2)%p;
}
LL lucas(int n, int m){
if(n<m)return 0;
if(n < p && m < p)return comb(n, m);
return lucas(n % p, m % p) * lucas(n / p, m / p) % p;
}
int main(){
int T;
read(T);
while(T--) {
int n, m;
read(n);read(m);read(p);
printf("%lld\n", lucas(n + m, m));
}
return 0;
}