Many Many Paths(组合计数)

题意

给定\(r1, c1, r2, c2\),求\(\sum\limits_{i=r1}^{r2} \sum\limits_{j=c1}^{c2} f(i,j)\),其中\(f(i,j)\)表示从\((0,0)\)往上或者往右走到\((i,j)\)的方案数。

题目链接:https://atcoder.jp/contests/abc154/tasks/abc154_f

数据范围

\(1 \leq r_1 \leq r_2 \leq 10^6\)
\(1 \leq c_1 \leq c_2 \leq 10^6\)

思路

参考blog:https://www.cnblogs.com/lllxq/p/12354597.html

第五行的公式,在前面加上一个\(\binom{i+1}{0}\),再减去一个\(\binom{i+1}{0}\),即可得到。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;

const int N = 2000010, mod = 1e9 + 7;

int r1, c1, r2, c2;
ll fac[N], infac[N];

ll qmi(ll a, ll b)
{
    ll res = 1;
    while(b) {
        if(b & 1) res = res * a % mod;
        b >>= 1;
        a = a * a % mod;
    }
    return res;
}

ll inv(ll a)
{
    return qmi(a, mod - 2);
}

ll C(ll x, ll y)
{
    return fac[x] * infac[y] % mod * infac[x - y] % mod;
}

void init()
{
    fac[0] = infac[0] = 1;
    for(int i = 1; i < N; i ++) fac[i] = fac[i - 1] * i % mod;
    for(int i = 1; i < N; i ++) infac[i] = infac[i - 1] * inv(i) % mod;
}

ll calc(int a, int b)
{
    ll res = 0;
    for(int i = 0; i <= a; i ++) {
        res = (res + C(i + b + 1, b)) % mod;
    }
    return res;
}

int main()
{
    init();
    scanf("%d%d%d%d", &r1, &c1, &r2, &c2);
    printf("%lld\n", ((calc(r2, c2) - calc(r1 - 1, c2) - calc(r2, c1 - 1) + calc(r1 - 1, c1 - 1)) % mod + mod) % mod);
    return 0;
}
posted @ 2022-09-26 17:09  pbc的成长之路  阅读(24)  评论(0编辑  收藏  举报