zoukankan      html  css  js  c++  java
  • AGC018E

    题意

    给出平面上三块不相交的从左上到右下排列的三块区域,求分别从这三个区域中挑一个点构成的路径方案数的和

    做法

    首先考虑转化求路径的方案数的式子。发现对于从原点出发,到$(x,y)$内所有点的所有可能路径数就是${x+1+y+1choose x+1}$,于是可以枚举中间那个区域选哪个点,然后通过那个点的路径数可以通过对另外两个区域分别用二维前缀和来求。优化非常巧妙,这个计数可以转化为对于每条通过中间区域的路径乘上在中间区域的点的数量,于是让通过左边或上面进入第二块区域的路径方案乘上一个负的factor,从下面或右边出去的乘上一个正的factor(具体看代码吧),即可达到这个目的。考虑每条通过中间区域的合法路径,将它出去的factor减去进来的factor,刚好就是在这个区域中通过的点的数量。

     1 #include <cstdio>
     2 #include <cstring>
     3 
     4 
     5 int fpow(int b, int i, int m) {
     6     int r = 1;
     7     for (; i; i >>= 1, b = b * 1LL * b % m)
     8         if (i & 1) r = r * 1LL * b % m;
     9     return r;
    10 }
    11 
    12 const int N = 2e6 + 100;
    13 const int M = 1e9 + 7;
    14 int X[6], Y[6];
    15 long long ans;
    16 long long fac[N], ifac[N];
    17 
    18 long long num(int x, int y) {
    19     //fprintf(stderr, "%d %d
    ", x, y);
    20     return fac[x + y] * 1LL * ifac[x] % M * ifac[y] % M;
    21 }
    22 
    23 int numPath0(int x, int y) {
    24     //fprintf(stderr, "0: %d %d
    ", x, y);
    25     long long ret = 0;
    26     ret += num(x - X[1], y - Y[1]);
    27     ret += num(x - X[0] + 1, y - Y[0] + 1);
    28     ret -= num(x - X[0] + 1, y - Y[1]);
    29     ret -= num(x - X[1], y - Y[0] + 1);
    30     return ((ret % M) + M) % M;
    31 }
    32 
    33 int numPath1(int x, int y) {
    34     //fprintf(stderr, "1: %d %d
    ", x, y);
    35     long long ret = 0;
    36     ret += num(X[4] - x, Y[4] - y);
    37     ret += num(X[5] - x + 1, Y[5] - y + 1);
    38     ret -= num(X[4] - x, Y[5] - y + 1);
    39     ret -= num(X[5] - x + 1, Y[4] - y);
    40     return ((ret % M) + M) % M;
    41 }
    42 
    43 
    44 int main() {
    45 #ifdef lol
    46     freopen("e.in", "r", stdin);
    47     freopen("e.out", "w", stdout);
    48 #endif
    49 
    50     fac[0] = 1;
    51     for (int i = 1; i < N; ++i)
    52         fac[i] = 1LL * fac[i - 1] * i % M;
    53     ifac[N - 1] = fpow(fac[N - 1], M - 2, M);
    54     for (int i = N - 2; 0 <= i; --i)
    55         ifac[i] = ifac[i + 1] * 1LL * (i + 1) % M;
    56 
    57     for (int i = 0; i < 6; ++i)
    58         scanf("%d", X + i);
    59     for (int i = 0; i < 6; ++i)
    60         scanf("%d", Y + i);
    61 
    62     ans = 0;
    63     for (int i = X[2]; i <= X[3]; ++i) {
    64         (ans += 1LL * (M - (i + Y[2])) * numPath0(i, Y[2] - 1) % M * numPath1(i, Y[2]) % M) %= M;
    65         (ans += 1LL * (i + Y[3] + 1) * numPath0(i, Y[3]) % M * numPath1(i, Y[3] + 1) % M) %= M;
    66     }
    67     for (int i = Y[2]; i <= Y[3]; ++i) {
    68         (ans += 1LL * (M - (i + X[2])) * numPath0(X[2] - 1, i) % M * numPath1(X[2], i) % M) %= M;
    69         (ans += 1LL * (i + X[3] + 1) * numPath0(X[3], i) % M * numPath1(X[3] + 1, i) % M) %= M;
    70     }
    71     printf("%lld
    ", ans);
    72 
    73     return 0;
    74 }
  • 相关阅读:
    img src 改变问题
    <a href="javascript:;" ></a>
    CSS先后顺序影响效果
    CSS学习遇到问题,注释问题
    关于某个网站的分析
    问题汇总
    作为一枚web前端开发工程师 这些CSS 小技巧你值得掌握
    web前端性能优化
    Sea.js学习笔记
    学习计划
  • 原文地址:https://www.cnblogs.com/ichn/p/7494183.html
Copyright © 2011-2022 走看看