A - Chat Group ( 乘法逆元 )
It is said that a dormitory with 6 persons has 7 chat groups ^_^. But the number can be even larger: since every 3 or more persons could make a chat group, there can be 42 different chat groups.
Given N persons in a dormitory, and every K or more persons could make a chat group, how many different chat groups could there be?
Input
The input starts with one line containing exactly one integer T which is the number of test cases.
Each test case contains one line with two integers N and K indicating the number of persons in a dormitory and the minimum number of persons that could make a chat group.
- 1 ≤ T ≤ 100.
- 1 ≤ N ≤ 109.
- 3 ≤ K ≤ 105.
Output
For each test case, output one line containing "Case #x: y" where x is the test case number (starting from 1) and y is the number of different chat groups modulo 1000000007.
Example Input
1
6 3
Output
Case #1: 42
题意:一个宿舍中又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) )
(a / b)%mod = a % mod *(b关于模mod的逆元);
扩展知识 : 组合数的递推公式
注: 一般是很大的数做乘除法再去模一个数的时候需要用乘法逆元。如该模的数是1e9+7, 直接用费马小定理求逆元inv(a) = qpow( a, mod-2 )。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
ll exgcd( ll a, ll b, ll &x, ll &y )
{
if ( b==0 ) {
x = 1;
y = 0;
return a;
}
ll re = exgcd(b,a%b,y,x);
y -= x*(a/b);
return re;
}
ll getni( ll a )
{
ll mod = 1e9+7,x,y;
ll gcd = exgcd( a,mod,x,y );
if ( gcd==1 ) {
if ( x>=0 ) return x%mod;
else return x%mod+mod;
}
else {
return -1;
}
}
ll qpow( ll a, ll n )
{
ll re = 1;
while ( n ) {
if ( n&1 ) {
re = (re*a)%mod;
}
a = (a*a)%mod;
n >>= 1;
}
return re;
}
int main()
{
ll listt,n,k,ji=1;
cin >> listt;
while ( listt-- ) {
cin >> n >> k;
ll ans = qpow(2,n) - 1;
ll now = 1;
for ( int i=1; i<k; i++ ) {
now = (((n-i+1)*now)%mod*qpow(i,mod-2))%mod;
ans = (ans-now)%mod;
}
if ( ans<0 ) ans = ans%mod+mod;
else ans = ans%mod;
cout << "Case #" << ji++ << ": " << ans << endl;
}
return 0;
}