1. 程式人生 > 實用技巧 >求組合數

求組合數

求組合數

1e4個詢問 2e3以內 p 遞推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-1]+c[i-1][j])%mod;
}

1e4個詢問 1e5以內 p 預處理階乘和階乘的逆元

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;
}
cin>>a>>b;
cout<<(LL)fact[a] * infact[b] % mod * infact[a - b] % mod<<endl;

20個詢問 1e18以內 p是1e5以內 盧卡斯定理

int C(int a,int b) {
    if (b > a) return 0;
    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(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;
}
cin>>a>>b>>p;
cout<<lucas(a,b)<<endl;

輸入a和b 5000以內 不進行取模 分解質因數後進行高精度乘法

bool st[N];
int primes[N];
int cnt;
int sum[N];
int a,b;
cin>>a>>b;
get_primes(N);
for(int i=0;i<cnt;i++) {
    int p = primes[i];
    sum[i] = primedivide3(a,p)-primedivide3(b,p)-primedivide3(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];