组合数
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MOD = 1e9 + 7;
const int maxn = 1e9 + 10;
inline int mul(int a,int b){
return ((a % MOD) * (b % MOD)) % MOD;
}
//快速幂计算(a^b) % MOD
inline int qpow(int a,int b) {
int ans = 1;
while(b){
if(b & 1) ans = (ans * a) % MOD;
a = mul(a,a);
b >>= 1;
}
return ans;
}
//计算b的逆元
inline int inv(int b) {
return qpow(b,MOD-2);
}
//计算(a / b) % MOD
inline int divv(int a,int b) {
return ((a%MOD)*(inv(b)%MOD))%MOD;
}
//mxx以内素数表
bool prime[maxn];
int cnt;
inline vector<int> nPrime(int mxx){
cnt = 0;
vector<int> v;
memset(prime, true, sizeof(prime));
prime[0] = prime[1] = false;///表明true为质数
for (int i = 2; i <= mxx; ++i){
if (prime[i]){
v.push_back(i),cnt++;
}
//此处边界判断为rec[j] <= maxn / i,如果写成i * rec[j] <= maxn,需要确保i * rec[j]不会溢出int
for (int j = 0; j < cnt && v[j] <= mxx / i; ++j){
prime[i * v[j]] = false;
if (i % v[j] == 0)
break;
}
}
return v;
}
//计算n!中素数m的次数
int dPrime(int n, int m) {
int pow = 0;
while (n >= m) {
int temp = n / m;
pow += temp;
n = temp;
}
return pow;
}
//极小数 时空复杂度 On O1
inline int calc1 (int a, int b){
int res = 1;
for(int i = 1;i <= b;i++){
res = mul(res, (a - b + i)) / i;
}
return res;
}
//较大数 时空复杂度 On O1 ,逆元求除
inline int calc2 (int a, int b){
int res = 1;
for(int i = 1;i <= b;i++){
res = mul(res, divv(a - b + i, i));
}
return res;
}
//极大数 时空复杂度 On ~ Ologn On ,分解质因数,阶段取乘,10000000以下上面的快, 20000000以上时这个快,中间看电脑
inline int calc3(int n, int m) {
int ans = 1;
vector<int> v = nPrime(n);
for (int i = 0; i < v.size(); i++) {
int k = v.at(i),pow;
pow = dPrime(n, k) - dPrime(m, k) - dPrime(n - m, k);
ans = mul(ans,qpow(k,pow));
}
return ans;
}
clock_t st,ed;
double endtime;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
printf("%lld\n",calc1(9,4));
//较大数下时间比较
st = clock();
printf("%lld\n",calc2(90000000,40000000));
ed = clock();
endtime=(double)(ed-st)/CLOCKS_PER_SEC;
cout << "Total time:" << endtime * 1000 << "ms" << endl; //ms为单位
st = clock();
printf("%lld\n",calc3(90000000,40000000));
ed = clock();
endtime=(double)(ed-st)/CLOCKS_PER_SEC;
cout << "Total time:" << endtime*1000 << "ms" << endl;
st = clock();
printf("%lld\n",calc2(90000000,40000000));
ed = clock();
endtime=(double)(ed-st)/CLOCKS_PER_SEC;
cout <<"Total time:" << endtime*1000 << "ms" << endl;
st = clock();
printf("%lld\n",calc3(90000000,40000000));
ed = clock();
endtime=(double)(ed-st)/CLOCKS_PER_SEC;
cout << "Total time:" << endtime*1000 << "ms" << endl;
return 0;
}