zoukankan      html  css  js  c++  java
  • [数论][组合数学]微信群

    题目描述

    众所周知,一个有着6个人的宿舍可以有7个微信群(^_^,别问我我也不知道为什么),然而事实上这个数字可以更大,因为每3个或者是更多的人都可以组建一个群,所以6个人最多可以组建42个不同的群。
    现在,已知一间宿舍有N个人,并且每至少K个人都可以组建一个微信群,那么他们最多可以组建多少个不同的微信群?

    输入

    一行两个整数N和K,表示宿舍中的人数和最少能够组建微信群的人数

    输出

    一行一个整数,即最多能组建多少个不同的微信群,由于这个数字很大,请输出对10^9+7求余后的结果

    样例输入

    6 3
    

    样例输出

    42
    

    提示

    对于30%的数据,3<=N<=10^3
    对于60%的数据,3<=N<=10^6
    对于100%的数据,3<=N<=10^9,3<=K<=10^5

    思路:要求C(n,k)+C(n,k+1)+...+C(n,n),转化为求2^n-(C(n,0)+C(n,1)+...+C(n,k-1))
    求组和数有这么几种方式:
    1.C(n,m)=n!/(n-m)!/m! (逆元求组合数——n,m不太大,而T又很大时,预处理)
    2.C(n,m)=C(n,m-1)*(n-m+1)/m (递推求组合数——n较大m不太大,而T又不大时)
    3.C(n,m)=C(n-1,m)+C(n-1,m-1)(递推求组合数——n,m不太大时,而T又很大时,预处理,不过用处似乎不大?)
    组合数的性质有:
    1.C(n,m)=C(n,n-m)
    2.C(n,0)+C(n,1)+...+C(n,n-1)+C(n,n)=2^n
     
    AC代码:
    #include <iostream>
    #include<cstdio>
    #define mod 1000000007
    typedef long long ll;
    using namespace std;
    
    ll n,k;
    
    ll qpow(ll a,ll b){
      ll ret=1;
      while(b){
        if(b&1) ret=(ret*a)%mod;
        a=(a*a)%mod;
        b>>=1;
      }
      return ret;
    }
    
    int main()
    {
        scanf("%lld%lld",&n,&k);
        ll ans=qpow(2,n);
        ll sum=1; ll tmp=1;
        for(ll i=1;i<=k-1;i++){
            tmp=tmp*(n-i+1)%mod*qpow(i,mod-2)%mod;
            sum=(sum+tmp)%mod;
        }
        ans=(ans-sum+mod)%mod;//防止出现负数
        printf("%lld
    ",ans);
        return 0;
    }
    转载请注明出处:https://www.cnblogs.com/lllxq/
  • 相关阅读:
    java常用设计模式链接
    常用设计模式汇总
    转:面试的角度诠释Java工程师(二)
    转:面试的角度诠释Java工程师(一)
    神经网络与深度学习_邱锡鹏——无监督学习和信息论
    智能推荐算法在直播场景中的应用
    经纬度地点之间距离测算
    <3>Transformer 到bert 模型
    <4>从bert到XLnet
    <2>自然语言难在哪? ----刘知远教授
  • 原文地址:https://www.cnblogs.com/lllxq/p/9038243.html
Copyright © 2011-2022 走看看