Question: Find the number of combinations C(n, m) (n is down, m is up)
Let’s first understand two little knowledge
Fermat's Lemma
This can be used to find the inverse element under special circumstances.
Inverse element
Definition: If a * x = 1(mod p), and gcd(a, p) = 1 (equivalent to a, p are relatively prime), then x is the multiplicative inverse of a in the sense of mod p.
According to the Fermat's little lemma above, we can know that if p is a prime number, then a^(p-1) = 1(mod p). It holds
that a^(p-2) is a modulo p Inverse element (only applicable to blogs where p is a prime number, the next time you add the inverse element)
Use the inverse element to find the division and take the modulus
Division cannot be directly modulo
Theorem: a/b% p = a*x% mod p = 1% p; (x is the inverse element of a in the sense of modulo p)
Proof: a/b * b * x = a * x (mod p) (b * x = 1(mod p) ); In
this way, the division between the number of combinations is solved.
Speaking code in sections:
quick power templates
ll Power(ll x, ll y) {
ll n = y, ans = 1, res = x;
while(n){
if(n & 1) ans = ans * res % mod;
n >>= 1;
res = res * res % mod;
}
return ans%mod;
}
Initialization: Find each factorial (mod p) and the inverse element of each factorial in the sense of mod p.
for(int i=1; i<=N; i++) C[i] = (C[i-1]*i) % mod;
inv[N-1] = Power(C[N-1], mod-2); //费马小引理求逆元。
for(int i=N-2; i>=0; i--) {
inv[i] = inv[i+1]*(i+1) % mod; //阶乘逆元递推关系。
}
Explain the recurrence formula of factorial (k!) − 1 (k!)^(-1)(k!)− 1 meanskkk的 阶乘 的 逆
(k!) - 1 = ((k - 1)! ∗ k) - 1 = (k - 1) - 1 ∗ k - 1 (k!) ^ {- 1} = ((k- 1)! * K) ^ {- 1} = (k-1) ^ {- 1} * k ^ {- 1}(k!)−1=((k−1)!∗k)−1=(k−1)−1∗k− 1
So:(k!) − 1 ∗ k = ((k − 1)!) − 1 (k!)^{-1}*k = ((k-1)!)^{-1}(k!)−1∗k=((k−1)!)−1
Number of final solution combinations
ll U(ll x, ll y) {
if(y > x || x < 0 || y < 0) return 0;
if(y == 0 || x == y) return 1;
//A(x,x) / (A(y,y) * A(x-y,x-y),转化成逆元相乘
return (C[x] * inv[y]%mod * inv[x-y]) % mod;
}
Total code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const ll N = 2e6+5;
ll C[N] = {
1};
ll inv[N];
ll Power(ll x, ll y) {
ll n = y, ans = 1, res = x;
while(n){
if(n & 1) ans = ans * res % mod;
n >>= 1;
res = res * res % mod;
}
return ans%mod;
}
ll U(ll x, ll y) {
if(y > x || x < 0 || y < 0) return 0;
if(y == 0 || x == y) return 1;
return (C[x] * inv[y]%mod * inv[x-y]) % mod;
}
int main() {
for(int i=1; i<=N; i++) C[i] = (C[i-1]*i) % mod;
inv[N-1] = Power(C[N-1], mod-2);
for(int i=N-2; i>=0; i--) {
inv[i] = inv[i+1]*(i+1) % mod;
}
ll t, a, b, temp;
scanf("%lld", &t);
while(t--) {
scanf("%lld%lld", &a, &b);
a--, b--;
a += b;
printf("%lld\n", U(a, b));
}
return 0;
}