zoukankan      html  css  js  c++  java
  • XidianOJ 1149 卡尔的技能 II

    --正文

    多重集合数 + 组合数取模

    首先求出没有限制的选择方法C(n+m-1,m)

    然后减掉至少有一个元素选择了k+1次的方法数,加上至少有两个元素选择了k+1次的方法数。。。以此类推

    然后是组合数的计算

       C(n,m) % p= (n! / (m! * (n-m)!)) % p 

    由乘法逆元的性质和费马小定理可以算出

       C(n,m)  % p= n! * (m!*(n-m)!)^(p-2)

    后面的幂次使用快速幂可以轻松算出

    #include <cstdio> 
    #include <cstring> 
    #include <algorithm> 
    #include <cmath> 
    #include <iostream> 
    using namespace std;  
    typedef long long LL;
    #define MOD 1000000007
    LL Fast_Mod(LL a,LL b){
        LL res = 1,base = a;
        while (b){
            if (b&1) res = (res*base) % MOD;
            base = (base*base) % MOD;
            b = b >> 1;
        }
        return res;
    }
    LL fac[2000009],invfac[2000009],n,m,k;
    void Getfac(LL p){
        fac[0] = 1;
        int i;
        for (i=1;i<=p;i++){
            fac[i] = (fac[i-1]*i) % MOD;
        }
        invfac[p] = Fast_Mod(fac[p],MOD-2);
        for (i=p-1;i>=0;i--){
            invfac[i] = (invfac[i+1]*(i+1)) % MOD;
        }
    }
    LL Lucas(LL n,LL m){
        if (n < m) return 0;
        return ((fac[n] % MOD)*(invfac[m] % MOD) % MOD) * (invfac[n-m] % MOD) % MOD;
    }
    int main(){ 
      Getfac(2000006);
      while(scanf("%lld %lld %lld",&n,&m,&k)!=EOF){ 
         long long i;
         long long res = Lucas(n+m-1,m),sign = -1;
         for (i=1;i<=n;i++,sign = -sign){
             long long tmp = m - (k+1)*i; 
             if (tmp < 0) break;
            res = (res % MOD + sign*Lucas(n,i)*Lucas(n+tmp-1,tmp)) % MOD;
         }
         printf("%lld
    ",(res+MOD) % MOD);
      } 
      return 0; 
    } 
  • 相关阅读:
    SQL Union 和Union All 的区别
    SqlHelper.cs
    转载WPF:创建你的第一个WPF项目
    数据库分页存储过程
    sql 常用基础查询
    创建表--自动编号字段且自增
    模糊查询
    模式的定义
    C#计算两个日期之间相差的天数
    优化SQL查询:如何写出高性能SQL语句
  • 原文地址:https://www.cnblogs.com/ToTOrz/p/6171359.html
Copyright © 2011-2022 走看看