Codeforces554C组合数学+费马小定理求逆元

http://codeforces.com/contest/554/problem/C
有k种颜色的气球,每种有ci个。
i颜色的最后一个气球必须在i+1颜色的最后一个气球的前面。
设总共有tot个气球。
考虑最后一种颜色的最后一个球必须放在最后面。最后一种颜色有c[k-1]个气球,所以方法为C(c[k-1]-1,tot-1)。保证最后一个球在最后。
此时总共还剩tot-c[k-1]个球。
在考虑倒数第二种颜色的最后一个球也必须放在最后的一个空位置上,那么方法又有C(c[k-2]-1,tot-c[k-1]-1)。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 1009
typedef long long ll;
const int mod = 1000000007;
int n;
int num[M];
ll qpow(ll x,ll n,ll mod)
{
    ll ans = 1;
    while(n)
    {
        if(n & 1) ans = ans * x % mod;
        x = x * x % mod;
        n >>= 1;
    }
    return ans;
}
ll C(ll a,ll b)
{
    ll s1 = 1, s2 = 1;
    for(int i = b - a + 1;i <= b;i++) s1 = s1*i%mod;
    for(int i = 1;i <= a;i++) s2 = s2*i%mod;
    ll inv = qpow(s2,mod-2,mod);
    return s1*inv%mod;
    //return (s1%(s2*mod))/s2;
}
int main()
{
    ios::sync_with_stdio(false);
    cin >> n;
    ll tot = 0;
    for(int i = 0;i < n;i++)
    {
        cin >> num[i];
        tot += num[i];
    }
    ll ans = 1;
    for(int i = n;i > 0;i--)
    {
        ans = ans * C(num[i]-1,tot-1) % mod;
        tot -= num[i];
    }
    cout << ans << endl;
    return 0;
}

你可能感兴趣的:(Codeforces554C组合数学+费马小定理求逆元)