abc042d <组合数>

发布时间 2023-06-19 10:57:15作者: O2iginal

https://atcoder.jp/contests/abc042/tasks/arc058_b-

// 分成两段, 计算组合数, 枚举分段点; 注意组合数需要使用递推, 否则超时
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;

int qpow(int a, int k, int m)
{
    a %= m;
    int res = 1;
    while (k)
    {
        if (k & 1) res = 1ll * res * a % m;
        k >>= 1;
        a = 1ll * a * a % m;
    }
    return res;
}


int C(int n, int k)
{
    if (k < 0 || k > n)  return 0;
    int res = 1;
    int t = 1;
    for (int i = 1, j = n; i <= k; i ++, j --)
    {
        res = 1ll * res * j % mod;
        t = 1ll * t * qpow(i, mod - 2, mod) % mod;
    }
    return 1ll * res * t % mod;
}

void solv()
{
    int h, w, a, b;
    cin >> h >> w >> a >> b;
    int res = 0;
    int row = h - a;
    int t1, t2;
    for (int col = b + 1; col <= w; col ++)
    {
        if (col == b + 1)
        {
            t1 = C(row + col - 2, col - 1);
            t2 = C((a-1)+ (w-col), a-1);
        }
        else  // 组合数递推
        {
            t1 = 1ll * t1 * (row+col-2) % mod * qpow(col-1, mod-2, mod) % mod;
            t2 = 1ll * t2 * (w - col + 1) %mod * qpow(a-1+w-col+1, mod-2, mod) % mod;
        }

        int t = 1ll * t1 * t2 % mod;
        res = (1ll * res + t) % mod;
        // cout << "col " << col  << " , row = " << row << "   t1 = " << t1 << "   t2 = " << t2 << endl;
    }
    cout << res << endl;

}

int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int T = 1;
    // cin >> T;
    while (T --)
    {
        solv();
    }
    return 0;
}