思路:先算出小于a的所有质数,再得出a、b、(a - b)的阶乘中包含的质数的次数,用get(a) - get(b) - get(a - b)即得出组合数中包含的各个质数的次数,然后利用大整数乘法,将这些质数(带次数)乘积算出来,即得结果
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 5010;
int prime[N], cnt;//记录质数和质数的个数
bool st[N];//记录一个数是不是质数
int sum[N];//记录一个质数在组合数中的次数
void get_prime(int n){//欧拉筛
for(int i = 2; i <= n; i ++ ){
if(!st[i]){
st[i] = true;
prime[cnt ++ ] = i;
}
for(int j = 0; j < cnt && prime[j] * i <= n; j ++ ){
st[prime[j] * i] = true;
if(i % prime[j] == 0) break;
}
}
}
int get(int a, int p){//计算a的阶乘中,质数p的次数,记模板
int res = 0;
while(a){
res += a / p;
a /= p;
}
return res;
}
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 main()
{
int a, b;
cin>>a>>b;
get_prime(a);//算出小于a的所有质数并记录
for(int i = 0; i < cnt; i ++ ){
int p = prime[i];
sum[i] = get(a, p) - get(b, p) - get(a - b, p);//记录组合数中含有某个质数的次数
}
vector<int> res;
res.push_back(1);//利用vector储存大整数乘法的结果
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 -- ){
cout<<res[i];
}
return 0;
}