注意事项:
代码涉及使用快速幂求乘法逆元的操作,可以看我之前的文章:java—快速幂—求逆元
题目:
输入:
3
3 1
5 3
2 2
输出:
3
10
1
public class 求组合数_2 {
//fact存储预处理的乘阶,infact存储预处理的乘阶逆元
public static int N = 100010, mod = 1000000007;
public static long[] fact = new long[N], infact = new long[N];
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
//这里切记要先初始化两个arr的0号位为1
fact[0] = infact[0] = 1;
for (int i = 1; i < N; i++) {
fact[i] = fact[i-1] * i % mod;
infact[i] = infact[i-1] * qmi(i, mod-2, mod) % mod;
}
//这里输出的时候不能把三个全乘到一起然后再%,因为会溢出
while (n-- > 0) {
int a = in.nextInt(), b = in.nextInt();
System.out.println(fact[a] * infact[b] % mod * infact[a-b] % mod);
}
}
//快速幂,原封不动
public static long qmi(long a, int k, int p) {
long res = 1;
while (k > 0) {
if ((k&1) == 1) res = res*a % p;
k >>= 1;
a = a*a % p;
}
return res;
}
}
思路:(为了避免计算除法取余,直接预处理乘阶和逆元,将除法替换为乘法)
注意:这种预处理法是在
1 < n < 10^5
1 <= a <= b <= 10^4
的情况下使用最优
声明:算法思路来源为y总,详细请见https://www.acwing.com/
本文仅用作学习记录和交流