快速幂:数论-----快速幂-优快云博客
快速幂求逆元:数论----快速幂求逆元-优快云博客
筛质数:筛质数----优快云博客
求组合数I //10万组 a,b<=2000,需要取mod //递推 O(n*n)
b a*(a-1)*...*(a-b+1) a!
C = --------------------------- = ------------
a 1*2*3*...*b b!(a-b)!
b b b-1
C =C + C (递推公式)
a a-1 a-1
#include<bits/stdc++.h>
using namespace std;
const int N=2010,mod=1e9+7;
int c[N][N];
void init(){
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]+c[i-1][j-1])%mod; //递推
}
int main(){
init();
int n;
cin>>n;
while(n--){
int a,b;
cin>>a>>b;
cout<<c[a][b]<<endl;
}
}
求组合数II 1万组(可以十万组) a,b<=100000 ,需要取mod // 预处理 (nlogn)
b a*(a-1)*...*(a-b+1) a!
C =------------------------------= ------------
a 1*2*3*...*b b!(a-b)!
fact[i]=i! mod 1e9+7; //fact[i] 表示 i 的阶乘
infact[i]=(i!)^(-1) mod 1e9+7; //infact[i] i 的阶乘的逆元 //快速幂求
a
C = fact[a] * infact[b-a] *infact[b]
b
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100010,mod=1e9+7;
int fact[N],infact[N];
int qmi(int a,int k,int p){
int res=1;
while(k){
if(k&1)res=(ll)res*a%p;
a=(ll)a*a%p;
k>>=1;
}
return res;
}
int main(){
fact[0]=infact[0]=1;
for(int i=1;i<N;i++){
fact[i]=(ll)fact[i-1]*i%mod;
infact[i]=(ll)infact[i-1]*qmi(i,mod-2,mod)%mod;
}
int n;
cin>>n;
while(n--){
int a,b;
cin>>a>>b;
cout<<(ll)fact[a]*infact[b]%mod*infact[a-b]%mod<<endl;
}
}
求组合数III 20组 a,b<=1e18 需要取mod // 卢卡斯定理lucas (p*log n * log p)
b b mod p b/p
C =C * C (mod p)
a a mod p a/p
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100010,mod=1e9+7;
int p;
int qmi(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(ll a,ll b){
int res=1;
for(int i=1,j=a;i<=b;i++,j--){
res=(ll)res*j%p;
res=(ll)res*qmi(i,p-2)%p;
}
return res;
}
int lucas(int a,int 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;
cin>>n;
while(n--){
ll a,b;
cin>>a>>b>>p;
cout<<lucas(a,b)<<endl;
}
}
求组合数IIII a,b<=5000 不需要取mod
// 算出组合数
b a*(a-1)*...*(a-b+1) a!
C =---------------------------- = ------------
a 1*2*3*...*b b!(a-b)!
1. 分解质因数 //筛1~5000以内的质数 求每个质数的次数
2. 高精度 //所有的质因子的乘积
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5010;
bool st[N];
int primes[N],cnt;
int sum[N];
void get_primes(int n)
{
for (int i = 2; i <= n; i ++ )
{
if (!st[i]) primes[cnt ++ ] = i; //不是质数,就加到数表里
for (int j = 0; primes[j] <= n / i; j ++ ) //从小到大枚举所有质数
{
st[primes[j] * i] = true; //筛掉
if (i % primes[j] == 0) break; //primes[j]一定是i的最小质因子
}
}
}
int get(int n,int p){
int res=0;
while(n){
res+=n/p;
n/=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_primes(a);
for(int i=0;i<cnt;i++){
int p=primes[i];
sum[i]=get(a,p)-get(b,p)-get(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, primes[i]);
for(int i=res.size()-1;i>=0;i--)cout<<res[i];
puts("");
}
6396






