原题链接:https://cses.fi/problemset/task/1079
Binomial Coefficients
Your task is to calculate n n n binomial coefficients modulo 1 0 9 + 7 10^9+7 1 0 9 + 7 .
A binomial coefficient ( a b ) \binom{a}{b} ( b a ) can be calculated using the formula a ! b ! ( a − b ) ! \frac{a!}{b!(a-b)!} b ! ( a − b )! a ! .
We assume that a a a and b b b are integers and 0 ≤ b ≤ a 0≤b≤a 0 ≤ b ≤ a .
The first input line contains an integer n n n : the number of calculations.
After this, there are n n n lines, each of which contains two integers a a a and b b b .
Output
Print each binomial coefficient modulo 1 0 9 + 7 10^9+7 1 0 9 + 7 .
Constraints
1 ≤ n ≤ 1 0 5 1≤n≤10^5 1 ≤ n ≤ 1 0 5
0 ≤ b ≤ a ≤ 1 0 6 0≤b≤a≤10^6 0 ≤ b ≤ a ≤ 1 0 6
Example
Input:
Output:
题目描述
求n n n 个组合数( a b ) \binom{a}{b} ( b a ) 模1 0 9 + 7 10^9+7 1 0 9 + 7 的结果(1 ≤ n ≤ 1 0 5 1≤n≤10^5 1 ≤ n ≤ 1 0 5 , 0 ≤ b ≤ a ≤ 1 0 6 0≤b≤a≤10^6 0 ≤ b ≤ a ≤ 1 0 6 )
解决方案
预计算所有a ≤ 1 0 6 a\le 10^6 a ≤ 1 0 6 范围内, a ! m o d ( 1 0 9 + 7 ) a!\mod(10^9+7) a ! mod ( 1 0 9 + 7 ) 的值,以及所有a ! a! a ! 的模逆元 的值,记为a ! − 1 a!^{-1} a ! − 1 ,则a ! b ! ( a − b ) ! ≡ a ! ∗ b ! − 1 ∗ ( a − b ) ! − 1 m o d ( 1 0 9 + 7 ) \frac{a!}{b!(a-b)!}\equiv a! * b!^{-1} * (a-b)!^{-1} \mod (10^9+7) b ! ( a − b )! a ! ≡ a ! ∗ b ! − 1 ∗ ( a − b ) ! − 1 mod ( 1 0 9 + 7 ) ;
时间复杂度
O ( n + log ( 1 0 9 + 7 ) ) O(n+\log(10^9+7)) O ( n + log ( 1 0 9 + 7 ))
计算某一个单独的数的模逆元的时间复杂度为时间复杂度为O ( log ( 1 0 9 + 7 ) ) O(\log(10^9+7)) O ( log ( 1 0 9 + 7 )) ,而a ! − 1 = ( a ) ! − 1 ( a + 1 ) − 1 ∗ ( a + 1 ) = ( a + 1 ) ! − 1 ∗ ( a + 1 ) a!^{-1}=(a)!^{-1}(a+1)^{-1}*(a+1)=(a+1)!^{-1}*(a+1) a ! − 1 = ( a ) ! − 1 ( a + 1 ) − 1 ∗ ( a + 1 ) = ( a + 1 ) ! − 1 ∗ ( a + 1 ) ,在O ( log ( 1 0 9 + 7 ) ) O(\log(10^9+7)) O ( log ( 1 0 9 + 7 )) 的时间复杂度内计算得到a ! a! a ! 后,即可通过递推得到( a − 1 ) ! − 1 (a-1)!^{-1} ( a − 1 ) ! − 1 ,( n − 2 ) ! − 1 (n-2)!^{-1} ( n − 2 ) ! − 1 …,预计算的总时间复杂度为O ( n + log ( 1 0 9 + 7 ) ) O(n+\log(10^9+7)) O ( n + log ( 1 0 9 + 7 )) ,计算每一个单独的组合数( a b ) \binom{a}{b} ( b a ) 的时间复杂度为O ( 1 ) O(1) O ( 1 ) ,共有n n n 个组合数要计算,因此总的时间复杂度为O ( n + log ( 1 0 9 + 7 ) ) O(n+\log(10^9+7)) O ( n + log ( 1 0 9 + 7 ))
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 #include <iostream> using namespace std;using ll = long long ;const int MAXN = 1e6 ;const int MOD = 1e9 + 7 ;ll fac[MAXN + 1 ]; ll inv[MAXN + 1 ]; ll exp (ll x, ll n, ll m) { x %= m; ll res = 1 ; while (n > 0 ) { if (n % 2 == 1 ) { res = res * x % m; } x = x * x % m; n /= 2 ; } return res; } void factorial () { fac[0 ] = 1 ; for (int i = 1 ; i <= MAXN; i++) { fac[i] = fac[i - 1 ] * i % MOD; } } void inverses () { inv[MAXN] = exp (fac[MAXN], MOD - 2 , MOD); for (int i = MAXN; i >= 1 ; i--) { inv[i - 1 ] = inv[i] * i % MOD; } } ll choose (int n, int r) { return fac[n] * inv[r] % MOD * inv[n - r] % MOD; }int main () { factorial (); inverses (); int n; cin >> n; for (int i = 0 ; i < n; i++) { int a, b; cin >> a >> b; cout << choose (a, b) << '\n' ; } }