$$ C_n^m = C_{n - 1}^{m} + C_{n - 1}^{m - 1} $$
求法一:递推
数据范围:$ 1 < T < 10 ^ 5$, $ 1 < a, b <2000 $
根据: $ C_n^m = C_{n - 1}^{m} + C_{n - 1}^{m - 1} $ 递推式得到如下代码:
#include<cstdio>
using namespace std;
const int N = 2001, mod = 1e9 + 7;
int n;
int c[N][N];
void init(){ //预处理
c[1][1] = c[0][1] = 1;
for(int i = 0;i < N;i ++)
for(int j = 0;j <= i;j ++)
if(!j) c[i][j] = 1;
else c[i][j] = (c[i - 1[j - 1] + d[i - 1][j]) % mod;
}
int main()
{
init();
scanf("%d",&n);
while(n --){
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",c[a][b]);
}
return 0;
}
解法二:快速幂 $ + $ 逆元
数据范围: $ 1 < T < 10 ^ 4$,$ 1 < a, b < 10^6 $
#include<cstdio>
using namespace std;
const int N = 1e5+10,mod = 1e9+7;
typedef long long LL;
int n;
int f[N],inf[N];
int imp(int a,int k,int q){
LL res = 1;
while(k){
if(k&1) res = (LL)res * a % q;
a = (LL)a * a % q;
k >>= 1;
}
return res;
}
void init(){
f[0] = inf[0] = 1;
for(int i = 1;i < N;i ++){
f[i] = (LL)f[i - 1] * i % mod;
inf[i] = (LL)inf[i - 1] * imp(i, mod - 2, mod) % mod;
}
}
int main(){
init();
scanf("%d",&n);
while(n --){
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",(LL)f[a] * inf[b] % mod * inf[a - b] % mod);
}
return 0;
}
解法三: 卢卡斯定理($ The $ $law $ $ of $ $lucas $)
数据范围: $ 1 < T < 20$, $ 1 < a, b < 10^{18} $, $ 1 < p < 10^8 $
$$ {{C_a^b} \equiv C_{a \mod\ p}^{b \mod \ {p}} \cdot C_{a / p}^{b / p}(\mod p)}$$
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
int p;
int imp(int a,int k){
int res = 1;
while(k){
if(k & 1) res = (LL)res * a % p;
a = (LL)a * a % p;
k >>= 1;
}
return res;
}
int C(int a,int b){
int res = 1;
for(int i = 1,j = a;i <= b;i ++,j --){
res = (LL)res * j % p;
res = (LL)res * imp(i, p - 2) % p;
}
}
int lucas(LL a,LL b){
if(a < p && b < p) return C(a, b);
return (LL)C(a % p, b % p) * lucas(a / p, b / p) % p;
}
int main(){
int n;
scanf("%d",&n);
while(n --){
LL a,b;
scanf("%lld%lld",&a,&b,&p);
printf("%lld\n",lucas(a,b));
}
return 0;
}
解法四:分解质因数$ + $高精
数据范围:$ 1 <a, b< 5000 $
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 5010;
int prime[N],cnt;
bool st[N];
int sum[N];
vector<int> mul(vector<int> a,int b){
vector<int>c;
int t = 0;
for(int i = 0;i < a.size(); i++){
t += a[i] * b;
c.push_back(t % 10);
t /= 10;
}
while(t){
c.push_back(t % 10);
t /= 10;
}
return c;
}
int work(int n,int p){
int res = 0;
while(n){
res += n / p;
n /= p;
}
return res;
}
void get_prime(int n){
for(int i = 2;i <= n;i ++){
if(!st[i]) prime[cnt ++] = i;
for(int j = 0; prime[j] <= n / i;j ++){
st[prime[j] * i] = true;
if(i % prime[j] == 0) break;
}
}
}
int main(){
int a,b;
scanf("%d%d",&a,&b);
get_prime(a);
for(int i = 0;i < cnt;i ++){
int p = prime[i];
sum[i] = work(a, p) - work(b, p) - work(a - b, p);
}
vector<int> res;
res.push_back(1);
for(int i = 0; i < cnt;i ++){
for(int j = 0;j < sum[i];j ++){
res = mul(res, prime[i]);
}
}
for(int i =res.size() - 1;i >= 0;i --){
printf("%d",res[i]);
}
return 0;
}
卢卡斯要求模数是质数