AtCoder - 1974(arc058_b)

题目链接


分析

组合数。枚举向右走了B格时向下走的格数[0..H-A-1],之后就相当于无限制位的矩阵走数。设向下走的格数为x,即为无限制位走到(x+1, B)位置,然后向右走一格走出限制列(x+1, B+1)(确保枚举的是第一次走出限制列的位置),最后即为从(x+1,B+1)到(H,W)的无限制位。则该情况下方案数为C(B+x-1, x) * C(H + W - 2 - B - x, H - 1 - x).累加每种情况,注意取模即可。(注意第一个组合数为C(B + x - 1, x))

代码

#define mod 1000000007
#define ll long long
ll exgcd(ll a, ll b, ll & x, ll & y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;   
    }
    ll d = exgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}
ll inv(ll a, ll MOD) {
    ll x, y;
    exgcd(a, MOD, x, y);
    x = (x % MOD + MOD) % MOD;
    return x;
}
ll fac[200010];
void init(int p) {
    fac[0] = 1;
    for (int i = 1; i <= p; i++) fac[i] = fac[i - 1] * i % mod;
}
ll lucas2(ll n, ll m) {
    ll ret = 1, a, b;
    while (n && m) {
        a = n % mod, b = m % mod;
        if (a < b) return 0;
        ret = ret * fac[a] % mod * inv(fac[b] * fac[a - b] % mod, mod) % mod;
        n /= mod, m /= mod;
    }
    return ret;
}
int main()
{
    ll x, y, n, m;

    scanf("%lld%lld%lld%lld", &n, &m, &x, &y);
    ll ans = 0;
    init(200005);
    ll z = y, p = n + m - 2;
    for (ll i = 0; i <= n - x - 1; i++) {
        ans = ans + lucas2(z + i - 1, i) * lucas2(p - z - i, n - 1 - i) % mod;
        ans %= mod;
        //printf("1  %lld  %lld\n", i, ans);
    }
    printf("%lld\n", ans);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值