AtCoder Beginner Contest 156 E-Roaming

E - Roming

解法:
我们假定有 i i i个房间空着,那么这 i i i个房间对于答案的贡献是 C n i C_n^i Cni,剩下的 n − 1 n-1 n1个房间中有 n n n个人,这样我们使用插空法,组合数是 C n − 1 n − i − 1 C_{n-1}^{n - i - 1} Cn1ni1
i i i可以取到 m i n ( k , n − 1 ) min(k,n-1) min(k,n1)
故答案是 ∑ i = 0 m i n ( k , n − 1 ) ( C n i ∗ C n − 1 n − i − 1 ) \sum_{i = 0}^{min(k,n-1)}(C_n^i * C_{n-1}^{n - i - 1}) i=0min(k,n1)(CniCn1ni1)

#include 

using namespace std;
typedef long long ll;
const ll p = 1e9 + 7;
const int N = 2e5 + 100;

ll fact[N],infact[N];
ll qpow(ll a,ll b)
{
    ll res = 1 % p;
    while(b)
    {
        if(b & 1)res = res * a % p;
        b >>= 1;
        a = a * a % p;
    }
    return res % p;
}
ll inv(ll m)
{
    return qpow(m,p-2) % p;
}
void init()
{
    fact[0] = 1,infact[0] = 1;
    for(int i = 1;i < N;i++)
    {
        fact[i] = (fact[i - 1] * i * 1ll) % p;
        infact[i] = inv(fact[i]) % p;
    }
}
ll C(ll m,ll n)
{
    if(m > n)return  0;
    return (fact[n] * infact[n - m] % p) * infact[m] % p;
}
int main()
{
    init();
    int n,k;
    cin >> n >> k;
    ll ans = 0;
    for(int i = 0;i <= min(k,n-1);i++)
    {
        ans = (ans +  C(i,n) * C(n - i - 1,n - 1) % p) % p;
    }
    cout << ans % p;
    
    return 0;
}

你可能感兴趣的:(数学)