码迷,mamicode.com
首页 > 其他好文 > 详细

组合数学(求C的两种方法)

时间:2021-04-14 12:43:08      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:题意   bsp   sum   force   空间   题目   初始化   解法   const   

整理一下求C 的两种方法

题目

题意

这道题主要就是求n组东东的放置方法,约束条件是在任意第i组放完之前,i-1组必须放完,问有多少放置方法

特点

组合数学+简单的DP,解法思路就是在任意放置i组时,除了最后一位一定是i,剩下任意插空放置

一种是用逆元求(适合数值大的适合)

int ksm(int a,int b,int p) {
    int res=1;
    while(b) {
        if(b&1)
            res=1ll*res*a%p;
        a=1ll*a*a%p;
        b>>=1;
    }
    return res;
}//快速幂
int c(int a,int b,int p) {
    if(b>a) return 0;
    int res=1;
    for(int i=1,j=a; i<=b; i++,j--) {
        res=res*j%p;
        res=res*ksm(i,p-2,p)%p;
    }
    return res;
}
int lucas(int a,int b,int p) {
    if(a<p &&b<p) return c(a,b,p);
    return c(a%p,b%p,p)*lucas(a/p,b/p,p)%p;
}

 

一种是暴力求(适合数值小的适合)

const int N = 1010;
int C[N][N];

void init() {
    C[0][0] = 1;
    for (int i = 1; i < N; i++) {
        C[i][0] = 1;//初始化 
        for (int j = 1; j <= i; j++) {
            C[i][j] = C[i-1][j] + C[i-1][j-1];
            //对于最后一位数取或不取的情况都要考虑 
            C[i][j] %= mod;
        }
    }
}

主函数

signed main() {
    init();
    int k=rd();
    vector<int> cnt(k + 1, 0), sum(k + 1, 0);
    vector<int> f(k + 1);
    //动态减少空间时间 
    int n = 0;
    for (int i = 1; i <= k; i++) {
        cnt[i]=rd();
        sum[i] += sum[i-1] + cnt[i];
    }
    f[1] = 1;
    for (int i = 2; i <= k; i++) {
//        f[i] = f[i-1] * C[sum[i-1] + cnt[i] - 1][cnt[i] - 1];//暴力方法
        f[i]=f[i-1]*lucas(sum[i-1]+cnt[i]-1,cnt[i]-1,mod);//不怎么暴力但慢一点的方法
        f[i] %= mod;
    }
    printf("%lld\n",f[k]);
    return 0;
    return 0;
}

 

组合数学(求C的两种方法)

标签:题意   bsp   sum   force   空间   题目   初始化   解法   const   

原文地址:https://www.cnblogs.com/firerunner/p/14656580.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!