Codeforces Round 925 (Div. 3)

题意:给你a,b,c,d个4种类型的方块,要求让你连成一条线;

思路:可以看出只有1,2可以改变图形的凹凸性,且必须交替排列,那么由此可以推出一种不能的情况,那就是abs(a-b)>1,无论如何交替都不可能,另一种就是ab都为0吗,但是3,4都存在这种也无解。

如何算有解呢,其实就是组合数,

将 x 个相同的物品放进 y 个盒子(允许不放)的方案数是 C(x+y-1,x-1)。

另一些组合数的公式  知识链接

那么根据我们上面的不可能的条件,我们可以分为a==b ,a==b+1,b==a+1,三种情况

  1:a==b

  1. 若 1 开头,则 3 有 a 个空位,4 有 a+1 个空位,方案数为 (c+a−1,a-1)*( d + a , a )。
  2. 若 2 开头,则 3 有 a+1 个空位,4 有 a 个空位,方案数为 (c+a, a)(d+a−1,a−1)。

2:a==b+1

仅有一种方案:以 1 开头。此时 3,4 均有 a个空位,方案数为 (c+a−1,a−1)(d+a−1,a−1)。

 3:b==a+1

以 2 开头。此时 3,4 均有 a+1 个空位,方案数为 (c+a,a ) (d+a,a)。

预处理阶乘、阶乘逆元即可做到 O(1) 组合数,按公式计算即可。

int fact[N], infact[N];
int qpow(int a, int b)
{
    int res = 1;
    while (b)
    {
        if (b & 1)
            res = res * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return res;
}
void init()
{
    fact[0] = 1;
    for (int i = 1; i <= N; i++)
        fact[i] = fact[i - 1] * i % mod;
    infact[N] = qpow(fact[N], mod - 2);
    for (int i = N; i >= 1; i--)
        infact[i - 1] = infact[i] * i % mod;
}
int C(int n, int m)
{
    return fact[n] * infact[m] % mod * infact[n - m] % mod;
}
void solve()
{
    int a, b, c, d;
    cin >> a >> b >> c >> d;
    if (abs(a - b) > 1)
        cout << 0 << endl;
    else if (a == 0 && b == 0)
    {
        if (c && d)
            cout << 0 << endl;
        else
            cout << 1 << endl;
    }
    else if (a == b)
    {
        int t1 = C(a - 1, a + c - 1) * C(a, a + d) % mod;
        int t2 = C(a, a + c) * C(a - 1, a + d - 1) % mod;
        cout << (t1 + t2) % mod << endl;
    }
    else
    {
        if (a == b + 1)
        {
            int t1 = C(a - 1, a + c - 1) * C(a - 1, a + d - 1) % mod;
            cout << t1 << endl;
        }
        else if (b == a + 1)
        {
            int t2 = C(a, a + c) * C(a, a + d) % mod;
            cout << t2 << endl;
        }
    }
}

你可能感兴趣的:(codeforces,c++,算法,组合数)