Chat Group

题意:一个宿舍中又n个人,最少k(k >= 3)个人就可以建一个讨论组,问最多可以建多少个不同的讨论组。

解答:C(n,k)+C(n,k+1)+.......+C(n,n)  =  2^n - ( C(n,0) + C(n,1) + C(n,2) + ......+C(n,k-1) )

知识点:费马小定理求逆元inv(a) = qpow( a, mod-2 )。 阶乘逆元:https://blog.csdn.net/Tc_To_Top/article/details/51203160

 1 //C(n, k) + C(n, k + 1) + ....... + C(n, n) = 2 ^ n - (C(n, 0) + C(n, 1) + C(n, 2) + ...... + C(n, k - 1))
 2 #define MAXN 100005
 3 #define mod 1000000007
 4 int t;
 5 int n, k;
 6 ll inv[MAXN];
 7 ll fac[MAXN], coeff[MAXN];
 8 ll QPow(ll x, ll n){ //快速幂计算
 9     ll ret = 1;
10     ll tmp = x % mod;
11     while (n){
12         if (n & 1) {
13             ret = (ret * tmp) % mod;
14         }
15         tmp = tmp * tmp % mod;
16         n >>= 1;
17     }
18     return ret;
19 }
20 void init(){
21     fac[0] = 1;
22     //fac数组是阶乘
23     for (int i = 1; i < MAXN; i++) {
24         fac[i] = fac[i - 1] * i % mod;
25     }
26     
27     //   费马小定理求逆元inv(a) = qpow( a, mod-2 )
28     //   inv数组存储k阶乘关于模mod的逆元
29     inv[MAXN - 1] = QPow(fac[MAXN - 1], mod - 2);
30     for (int i = MAXN - 2; i >= 0; i--) {
31         //inv[i] = inv[i + 1] * (i + 1) % mod;
32         inv[i] = QPow(fac[i], mod - 2);         
34     }
35 }
36 int main() {
37     cin >> t;
38     init();
39     for(int tn = 1;tn <= t; tn++) {
40         cin >> n >> k;
41         ll ans = (QPow(2, n) - 1 + mod) % mod;
42         coeff[0] = 1;
43         for (int i = 1; i < k; i++) {
44             //  (a / b) % mod = a *(b关于模mod的逆元)% mod;
45             //   C(n,k)=(n-k+1)/k * C(n,k-1)  k从1走到k-1                        
46             // C(n,1)=C(n,0)*(n-1+1)/1   C(n,2)=C(n,1)*(n-2+1)/2  C(n,3)=C(n,2)*(n-3+1)/3
47             //  令a =coeff[k]=(n-k+1) * C(n,k-1)    b=k
48             //  C(n,k) = coeff[k] / k!
49             
50             coeff[i] = coeff[i - 1] * (n - i + 1) % mod;
51             ans = (ans - coeff[i] * inv[i] % mod + mod) % mod;
52         }
53         printf("Case #%d: %lld\n", tn, ans);
54     }
55     return 0;
56 }

 

posted @ 2020-08-01 18:22  吉吉的奥利奥  阅读(17)  评论(0编辑  收藏