组合数

 

1.求阶乘

 

#include<cstdio>
const int N = 20;
const int MOD = 1e9 + 7;
int fac[N];
void init(){
    fac[0] = 1;
    for(int i=1; i<N-1; i++)
        fac[i] = fac[i-1] * i;
}
int main(){
    init();
}

 

2.求组合数

(1)直接按定义求

(2)递推公式求   下标加1上标取大

#include<cstdio>
const int N = 50;
const int MOD = (int)1e9 + 7;
int comb[N][N];//comb[n][m]就是C(n,m)
void init(){
    for(int i = 0; i < N; i ++){
        comb[i][0] = comb[i][i] = 1;
        for(int j = 1; j < i; j ++){
            comb[i][j] = comb[i-1][j] + comb[i-1][j-1];
        }
    }
}
int main(){
    init();
}

 

 

3.组合数取模

 

LL Comb(LL a,LL b, LL p)
{
    if(a < b) return 0;
    if(a == b) return 1;
    if(b > a-b) b = a-b;
    LL ans = 1, ca = 1, cb = 1;
    for(LL i=0; i<b; ++i)
    {
        ca = (ca*(a-i))%p;
        cb = (cb*(b-i))%p;
    }
    ans = (ca*Power_mod(cb, p-2, p))%p;
    return ans;
}

 

4.卢卡斯定理

 

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
LL Power_mod(LL a, LL b, LL p)
{
    LL res = 1;
    while(b!=0)
    {
        if(b&1) res = (res*a)%p;
        a = (a*a)%p;
        b >>= 1;
    }
    return res;
}
LL Comb(LL a,LL b, LL p)
{
    if(a < b) return 0;
    if(a == b) return 1;
    if(b > a-b) b = a-b;
    LL ans = 1, ca = 1, cb = 1;
    for(LL i=0; i<b; ++i)
    {
        ca = (ca*(a-i))%p;
        cb = (cb*(b-i))%p;
    }
    ans = (ca*Power_mod(cb, p-2, p))%p;
    return ans;
}
LL Lucas(int n, int m, int p)
{
    LL ans = 1;
    while(n && m && ans)
    {
        ans = (ans * Comb(n%p, m%p, p))%p;
        n /= p;
        m /= p;
    }
    return ans;
}
int main()
{
    int n,m,p;
    while(scanf("%d%d%d",&n,&m,&p) !=EOF)
    {
        printf("%lld\n",Lucas(n,m,p));
    }
    return 0;
}

 

posted @ 2018-11-01 21:49  西风show码  阅读(203)  评论(0编辑  收藏  举报