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;

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章