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