AtCoder ABC 154F Many Many Paths
题目链接:https://atcoder.jp/contests/abc154/tasks/abc154_f
题目大意
设$(r, c)$为二维坐标轴上的整数点,且r, c均为自然数。
定义$f(r, c)$为从$(0, 0)$到$(r, c)$的所有路径总数(只能向上或向右走)。
现给定两个点$(r1, c1)$和$(r2, c2)$$(r1 \leq r2, c1 \leq c2)$,求$\displaystyle \sum_{i=r1}^{r2} \sum_{j=c1}^{c2} f(i, j)$, 并对$10^9 + 7$取模。
分析
不难看出,$f(r, c) = \binom{r + c}{r}$。
而$\displaystyle \sum_{j=c1}^{c2} f(r, j) = \displaystyle \sum_{j=c1}^{c2} \binom{r + j}{r} = \displaystyle \sum_{j=0}^{c2} \binom{r + j}{r} - \displaystyle \sum_{j=0}^{c1 - 1} \binom{r + j}{r}$。
利用朱世杰恒等式,可得$\displaystyle \sum_{j=c1}^{c2} f(r, j) = \binom{r + c2 + 1}{r + 1} - \binom{r + c1}{r + 1}$。
代码如下
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 /*-------------------Define Start-------------------*/ 5 typedef bool BL; // 布尔类型 6 typedef char SB; // 有符号1字节,8位 7 typedef unsigned char UB; // 无符号1字节,8位 8 typedef short SW; // 有符号短整型,16位 9 typedef unsigned short UW; // 无符号短整型,16位 10 typedef long SDW; // 有符号整型,32位 11 typedef unsigned long UDW; // 无符号整型,32位 12 typedef long long SLL; // 有符号长整型,64位 13 typedef unsigned long long ULL; // 无符号长整型,64位 14 typedef char CH; // 单个字符 15 typedef float R32; // 单精度浮点数 16 typedef double R64; // 双精度浮点数 17 18 #define Rep(i, n) for (register SDW i = 0; i < (n); ++i) 19 #define For(i, s, t) for (register SDW i = (s); i <= (t); ++i) 20 #define rFor(i, t, s) for (register SDW i = (t); i >= (s); --i) 21 #define foreach(i, c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i) 22 #define ms0(a) memset(a,0,sizeof(a)) 23 #define msI(a) memset(a,0x7f,sizeof(a)) 24 #define LOWBIT(x) ((x)&(-x)) 25 26 #define MP make_pair 27 #define PB push_back 28 #define ft first 29 #define sd second 30 31 #define pr(x) cout << #x << " = " << x << " " 32 #define prln(x) cout << #x << " = " << x << endl 33 34 const ULL mod = 1e9 + 7; //常用模数(可根据题目需要修改) 35 const ULL inf = 0x7fffffff; //用来表示无限大 36 const ULL infLL = 0x7fffffffffffffffLL; //用来表示无限大 37 /*-------------------Define End-------------------*/ 38 39 const UDW maxN = 1e6 + 7; 40 SLL r1, c1, r2, c2; 41 SLL ans; 42 43 SLL fac[maxN * 2]; 44 void init_fact() { 45 fac[0] = 1; 46 For(i, 1, 2 * maxN - 1) { 47 fac[i] = (i * fac[i - 1]) % mod; 48 } 49 } 50 51 void input(){ 52 cin >> r1 >> c1 >> r2 >> c2; 53 init_fact(); 54 } 55 56 //ax + by = gcd(a, b) = d 57 // 扩展欧几里德算法 58 /** 59 * a*x + b*y = 1 60 * 如果ab互质,有解 61 * x就是a关于b的逆元 62 * y就是b关于a的逆元 63 * 64 * 证明: 65 * a*x % b + b*y % b = 1 % b 66 * a*x % b = 1 % b 67 * a*x = 1 (mod b) 68 */ 69 inline void ex_gcd(SLL a, SLL b, SLL &x, SLL &y, SLL &d){ 70 if(!b) { 71 d = a, x = 1, y = 0; 72 } 73 else{ 74 ex_gcd(b, a % b, y, x, d); 75 y -= x * (a / b); 76 } 77 } 78 79 // 求a关于p的逆元,如果不存在,返回-1 80 // a与p互质,逆元才存在 81 inline SLL inv_mod(SLL a, SLL p = mod){ 82 SLL d, x, y; 83 ex_gcd(a, p, x, y, d); 84 return d == 1 ? (x % p + p) % p : -1; 85 } 86 87 inline SLL comb_mod(SLL m, SLL n) { 88 SLL ret; 89 90 if(m > n) { 91 swap(m, n); 92 } 93 94 ret = (fac[n] * inv_mod(fac[m], mod)) % mod; 95 ret = (ret * inv_mod(fac[n - m], mod)) % mod; 96 97 return ret; 98 } 99 100 void solve(){ 101 For(i, r1, r2) { 102 ans = (ans + comb_mod(i + 1, c2 + i + 1) - comb_mod(i + 1, c1 + i) + mod) % mod; 103 } 104 } 105 106 void output(){ 107 cout << ans << endl; 108 } 109 110 int main() { 111 input(); 112 solve(); 113 output(); 114 return 0; 115 }