AcWing 886:求组合数 II ← 费马小定理 + 快速冥 + 阶乘逆元
【题目来源】
【题目描述】
给定 n 组询问,每组询问给定两个整数 a,b,请你输出 C(a,b) mod (10^9+7) 的值。
【输入格式】
第一行包含整数 n。
接下来 n 行,每行包含一组 a 和 b。
【输出格式】
共 n 行,每行输出一个询问的解。
【输入样例】
3
3 1
5 3
2 2
【输出样例】
3
10
1
【数据范围】
1≤n≤10000,
1≤b≤a≤10^5
【算法分析】
● 本题与“AcWing 885:求组合数 I”()的区别仅仅在于 a、b 的数据规模不同,达到了 10^5。
● C(n, m) 在数学中通常表示组合数,即从 n 个不同元素中选取 m 个元素的组合数目,计算公式为:n! / (m! * (n-m)!)。
● 组合数在“数位DP”中经常用到。
● 阶乘逆元的计算核心是费马小定理。当模数 p 为质数时,费马小定理给出 a^(p-1) ≡ 1 (mod p),从而 a × a^(p-2) ≡ 1 (mod p),表明 a 的逆元为 a^(p-2) mod p。
● 快速幂是计算 a^(p-2) mod p 的高效工具,定义为 fastPow(a, p-2, p)。它将逆元求解的时间复杂度降至 O(log p)。
● 快速幂求逆元仅适用于模数 p 为质数的情况。
● 代码中 MOD=1e9+7 是常用质数。
● 定义 fac[i]=i! % p,invfac[i]=(i!)^(-1) % p。其中,p 为质数。
已知 1/i! = 1/(i-1)! * 1/i,而 1/i 为 i 的逆元,利用费马小定理知 i 的逆元等于 i^(p-2) mod p。综上可得,invfac[i] = invfac[i-1] * fastPow(i, p-2, p)。
【算法代码】
【参考文献】

浙公网安备 33010602011771号