求组合数
例子
思路
题目范围过大,必须预处理 , 仅仅考组合数递归来预处理不够,1e5 * 1e5已经超了 , 故预处理fact[a] , infact[a- b] ,infact[b] (infact 指的是逆元)
代码
using namespace std ;
typedef long long LL;
const int N = 100200, mod = 1e9 +7;
int fact[N] ,infact[N];
//int c[N][N];
int qpow(int i , int p ,int m)
{
int res = 1;
while(p){
if(p & 1) res = (LL)res * i % m;
p >>= 1;
i = (LL)i * i % mod ;
}
return res;
}
void init(){
fact[0] = infact[0] =1;
for(int i = 1; i < N ; i ++){
fact[i] = (LL)fact[i-1] * i % mod ;
infact[i] = (LL)infact[i-1] * qpow(i , mod-2 , mod) % mod;
// 根据逆元的特性 求infact[i-1 ]就是在求1 / fact[i-1](模 mod) , 并且根据费马小定理 , 因为mod 为质数 ,1 / i 的逆元 (模 mod )就是 qpow(i , mod-2 , mod) % mod ,利用到快速幂
}
}
int main(){
init();
int n;
cin >> n;
while(n--){
int a ,b;
cin >> a >>b;
printf("%d\n" , (LL)fact[a] * infact[a - b] % mod * infact[b] % mod);
}
return 0;
}
总结
- 求组合数需要根据不同的数据范围来选择不同的算法