zoukankan      html  css  js  c++  java
  • 组合数计算

    组合数取模就是求C(n,m)%MOD的值

    当m<=1000,n<=1000时,根据 C[i][j]=(C[i-1][j]+C[i-1][j-1])的性质,可以通过递推预处理出所有的组合数

    void init2()  //预处理组合数
    {
        for(int i=0;i<=1000;i++)
            C[i][0]=1;
       for(int i=1;i<=1000;i++)
       {
           for(int j=1;j<=i;j++)
            C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;
       }
    }

     利用阶乘进行的线性求组合数

    LL quick_pow(LL a,LL b)
    {
       LL ans=1;
       a=a%MOD;
       while(b>0)
       {
          if(b&1) ans=(ans*a)%MOD;
          b>>=1;
          a=(a*a)%MOD;
       }
       return ans;
    }
    void fac_init()
    {
      fac[0]=1;
      for(int i=1;i<=100010;i++)
      fac[i]=fac[i-1]*i%MOD;
    }
    LL C(LL a,LL b)
    {
      return fac[a]*quick_pow(fac[a-b],MOD-2)%MOD*quick_pow(fac[b],MOD-2)%MOD;//要求MOD是素数
    }

    对于大范围的组合数

     引用自http://blog.csdn.net/acdreamers/article/details/8037918;

          

    (2),并且是素数

         这个问题有个叫做Lucas的定理,定理描述是,如果

         

         那么得到

         

       

         这样然后分别求,采用逆元计算即可。

    题目:http://acm.fzu.edu.cn/problem.php?pid=2020

    题意:,其中,并且是素数。

    注意套用模板的时候 一定要保证p是素数

    #include <iostream>
    #include <string.h>
    #include <stdio.h>
    
    using namespace std;
    typedef long long LL;
    
    LL n,m,p;
    
    LL quick_mod(LL a, LL b)
    {
        LL ans = 1;
        a %= p;
        while(b)
        {
            if(b & 1)
            {
                ans = ans * a % p;
                b--;
            }
            b >>= 1;
            a = a * a % p;
        }
        return ans;
    }
    
    LL C(LL n, LL m)
    {
        if(m > n) return 0;
        LL ans = 1;
        for(int i=1; i<=m; i++)
        {
            LL a = (n + i - m) % p;
            LL b = i % p;
            ans = ans * (a * quick_mod(b, p-2) % p) % p;
        }
        return ans;
    }
    
    LL Lucas(LL n, LL m)
    {
        if(m == 0) return 1;
        return C(n % p, m % p) * Lucas(n / p, m / p) % p;
    }
    
    int main()
    {
        int T;
        scanf("%d", &T);
        while(T--)
        {
            scanf("%I64d%I64d%I64d", &n, &m, &p);
            printf("%I64d
    ", Lucas(n,m));
        }
        return 0;
    }
  • 相关阅读:
    Miller-Rabin素性测试
    ###Canny边缘检测算子
    ###SIFT特征
    建立一个免费的网站
    ###C中的extern-static-const关键词
    ###Git使用问题
    ###Fedora下安装Retext
    ###使用phpmailer自动邮件提醒
    Markdown学习
    有线和无线同时连接,选择其一上网
  • 原文地址:https://www.cnblogs.com/a249189046/p/7353999.html
Copyright © 2011-2022 走看看