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 }
  • 相关阅读:
    如何在Eclipse中彻底修改一个项目名称
    用JS在html页面实现打印功能
    关于git提交、还原使用
    maven package:Max maven Unsupported major.minor version 51.0
    Tomcat 启动报错:javax.naming.NamingException: No naming context bound to this class loader
    maven web 项目中启动报错java.lang.ClassNotFoundException: org.springframework.web.util.Log4jConfigListener
    tripwire检查文件完整性
    设置mysql表名不区分大小写
    mysql-零基础安装
    nginx-0基础安装篇
  • 原文地址:https://www.cnblogs.com/ichn/p/7494183.html
Copyright © 2011-2022 走看看