原题链接:https://cses.fi/problemset/task/1079

Binomial Coefficients

Your task is to calculate nn binomial coefficients modulo 109+710^9+7.
A binomial coefficient (ab)\binom{a}{b} can be calculated using the formula a!b!(ab)!\frac{a!}{b!(a-b)!}.
We assume that aa and bb are integers and 0ba0≤b≤a.

Input

The first input line contains an integer nn: the number of calculations.

After this, there are nn lines, each of which contains two integers aa and bb.

Output

Print each binomial coefficient modulo 109+710^9+7.

Constraints

1n1051≤n≤10^5

0ba1060≤b≤a≤10^6

Example

Input:

1
2
3
4
3
5 3
8 1
9 5

Output:

1
2
3
10
8
126

题目描述

nn个组合数(ab)\binom{a}{b}109+710^9+7的结果(1n1051≤n≤10^5, 0ba1060≤b≤a≤10^6

解决方案

预计算所有a106a\le 10^6范围内, a!mod(109+7)a!\mod(10^9+7)的值,以及所有a!a!模逆元的值,记为a!1a!^{-1},则a!b!(ab)!a!b!1(ab)!1mod(109+7)\frac{a!}{b!(a-b)!}\equiv a! * b!^{-1} * (a-b)!^{-1} \mod (10^9+7)

时间复杂度

O(n+log(109+7))O(n+\log(10^9+7))

计算某一个单独的数的模逆元的时间复杂度为时间复杂度为O(log(109+7))O(\log(10^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),在O(log(109+7))O(\log(10^9+7))的时间复杂度内计算得到a!a!后,即可通过递推得到(a1)!1(a-1)!^{-1}(n2)!1(n-2)!^{-1} …,预计算的总时间复杂度为O(n+log(109+7))O(n+\log(10^9+7)),计算每一个单独的组合数(ab)\binom{a}{b}的时间复杂度为O(1)O(1),共有nn个组合数要计算,因此总的时间复杂度为O(n+log(109+7))O(n+\log(10^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';
}
}