思路:先算出小于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; }