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 }
View Code

 

posted @ 2020-02-12 11:35  梦樱羽  阅读(264)  评论(0编辑  收藏  举报
Live2D