q q q组询问,每组询问两个整数,求 C n m m o d ( 1 0 9 + 7 ) C_n^m\bmod (10^9+7) Cnmmod(109+7)
数据范围 1 < = m < = n < = 2000 ,求 q < = 1 0 4 1<=m<=n<=2000,求q<=10^4 1<=m<=n<=2000,求q<=104
递推公式 C n m = C n − 1 m + C n − 1 m − 1 C_n^m=C_{n-1}^m+C_{n-1}^{m-1} Cnm=Cn−1m+Cn−1m−1
对于第一个数有选或者不选两个决策:
杨辉三角公式:
const int N = 2010,mod=1e9+7;
int c[N][N];
void init(){
for(int i=0;i<N;i++) c[i][0]=1;
for(int i=1;i<N;i++)
for(int j=1;j<=i;j++)
c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
}
q q q组询问,每组询问两个整数,求 C n m m o d ( 1 0 9 + 7 ) C_n^m\bmod (10^9+7) Cnmmod(109+7)
数据范围 1 < = m < = n < = 1 0 5 , q < = 1 0 4 1<=m<=n<=10^5,q<=10^4 1<=m<=n<=105,q<=104
C n m = n ! ( n − m ) ! m ! C_n^m=\frac{n!}{(n-m)!m!} Cnm=(n−m)!m!n!,用 f [ x ] 存 x ! m o d p f[x]存x!\bmod p f[x]存x!modp,用 g [ x ] 存 ( x ! ) − 1 m o d p g[x]存(x!)^{-1}\bmod p g[x]存(x!)−1modp,即乘法逆元
由于 p p p是质数,n,m都是小于p的,所以n,m与p互质,由费马小定理: a ⋅ a p − 2 ≡ 1 ( m o d p ) a·a^{p-2}\equiv1(\bmod p) a⋅ap−2≡1(modp),乘法逆元为 a p − 2 a^{p-2} ap−2
查询: C n m ( m o d p ) = f [ n ] ∗ g [ n − m ] ∗ g [ m ] ( m o d p ) C_n^m(\bmod p)=f[n]*g[n-m]*g[m](\bmod p) Cnm(modp)=f[n]∗g[n−m]∗g[m](modp)
const int N=1e5+10,mod=1e9+7;
int f[N],g[N];
LL qmi(LL a,LL b){
LL res=1;
while (b){
if (b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
void init(){
f[0]=g[0]=1;
for(int i=1;i<N;i++){
f[i]=f[i-1]*i%mod;
g[i]=g[i-1]* qmi(i,mod-2)%mod;
}
}
LL get(LL n,LL m){
return f[n]*g[m]%mod*g[n-m]%mod;
}
求 C n m m o d ( p ) C_n^m\bmod (p) Cnmmod(p),p为质数
数据范围 1 < = m < = n < = 1 0 18 , p < = 1 0 5 1<=m<=n<=10^{18},p<=10^5 1<=m<=n<=1018,p<=105
卢卡斯定理:
C n m = C n p m p C n m o d p m m o d p ( m o d p ) C_n^m=C^{\frac{m}{p}}_{\frac{n}{p}}C^{m\bmod p}_{n\bmod p} (\bmod p) Cnm=CpnpmCnmodpmmodp(modp),其中p为质数
#include
using namespace std;
#define endl '\n'
#define debug(x) cout<<"a["<<x<<"]="<<a[x]<<endl;
#define pr(x) cout<<x<<endl;
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
typedef long long LL;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const int N=1e5+10;
LL f[N],g[N];
LL qmi(LL a,LL b,int mod){
LL res=1;
while (b){
if (b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
void init(int mod){
f[0]=g[0]=1;
for(int i=1;i<N;i++){
f[i]=f[i-1]*i%mod;
g[i]=g[i-1]* qmi(i,mod-2,mod)%mod;
}
}
LL get(LL n,LL m,int mod){
return f[n]*g[m]%mod*g[n-m]%mod;
}
LL lucas(LL n,LL m,int mod){
if (m==0) return 1;
return lucas(n/mod,m/mod,mod)* get(n%mod,m%mod,mod)%mod;
}
int main() {
IOS;
#ifndef ONLINE_JUDGE
freopen("/Users/houyunfei/CLionProjects/MyCppWorkSpace/test.in", "r", stdin);
freopen("/Users/houyunfei/CLionProjects/MyCppWorkSpace/test.out", "w", stdout);
#endif
int n,m,mod;
int t;
cin>>t;
while (t--){
cin>>n>>m>>mod;
init(mod);
pr(lucas(n+m,m,mod))
}
return 0;
}