2017 ACM-ICPC Problem 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

对于此题来讲,有几个重点。首先要知道快速幂,其次知道排列组合的递推公式,最后要知道取模后除法和减法会出现问题,需要用费马小定理来解决和加模数再取模来解决。

除法不满足取模,那么我们可以求模的逆元来进行求结果,既然乘法可以取模,如果这个数除以一个数,那么我们可以让他乘以一个数使得和除以那个数的结果相同,那么乘的这个数就是那个数的乘法逆元


#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int M=1e9+7;
typedef long long ll;

ll quick(ll a,ll b)      //快速幂
{
    ll ans=1;
    a=a%M;
    while(b)
    {
        if(b&1)
            ans=ans*a%M;
        b>>=1;
        a=a*a%M;
    }
    return ans;
}

ll Cab(ll n,ll k)       //求C(n,k)
{
    int temp=1;
    for(int i=1; i<=k; i++)
    {
        temp=(temp%M*(n-i+1)%M*quick(i,M-2))%M;
    }
    return temp%M;
}



int main()
{
    int ca=0;
    int T;
    cin>>T;
    while(T--)
    {
        ll N,K,temp,ans;
        scanf("%I64d%I64d",&N,&K);

        if(K>=N/2)
        {
            ans=temp=Cab(N,K);
            for(ll i=K+1; i<=N; i++)
            {
                temp=(temp%M*(N-i+1)%M*quick(i,M-2))%M;     //此处用了费马小定理
                ans=(ans+temp)%M;
            }

        }
        else
        {

            ll result=quick(2,N);
            ans=temp=1;

            for(ll i=1; i< K; i++)
            {

                temp=(temp%M*(N-i+1)%M*quick(i,M-2))%M;
                ans=(ans+temp)%M;
            }
            ans=(M+result-ans)%M;      //注意减法取模问题
        }

        printf("Case #%d: %I64d\n",++ca,ans);
    }

    return 0;

}

猜你喜欢

转载自blog.csdn.net/qq_40861069/article/details/80315436