AGC018E Sightseeing Plan

题目链接 参考博客

从左下矩形出发经过中间矩形的一个点 \(p\) 再到右上矩形的方案数。值域 \(\le 10^6\),方案不同的意思是 \(p\) 或 路径上的点集不同。


(默认向上为 \(x\) 轴正方向,向右为 \(y\) 轴正方向)

这题好不可做啊,简化一下试试?

点到点

\[(x,y) \to (x',y') = G((x,y),(x',y')) = {x'-x+y'-y \choose x'-x} \]

点到矩形

\[\begin{aligned} &G((0,0), (x,y))\\ &= F(x,y)\\ &= \sum_{i=0}^xF(i,y-1)\\ &= \sum_{i=0}^xF(i,y-2) + \sum_{i=0}^{x-1}F(i,y-1)\\ &= ...\\ &= \sum_{i=0}^{x-1}\sum_{j=0}^{y-1}F(i,j) + F(0,y)\\ &= \sum_{i=0}^{x-1}\sum_{j=0}^{y-1}F(i,j) + 1 \end{aligned}\]

差分即可。

\[F(x' + 1, y' + 1) - F(x, y' + 1) - F(x' + 1, y') + F(x, y) \]

矩形到矩形

\[\begin{aligned} &\sum_{i=0}^{fx}\sum_{j=0}^{fy}\sum_{(k,l)\in Mat_2} G((i,j),(k,l))\\ &= \sum_{(i,j) \in Mat_1}G((i,j),(x_0,y_0) + ... + G((i,j),(x_3,y_3))\\ &= G((x_0',y_0'),(x_0,y_0)) + ... + G((x_3',y_3'),(x_3,y_3)) \end{aligned}\]

差分再差分,\(4 \times 4\) 次计算。

矩形经过矩形到矩形

枚举中间矩形的“进入”操作,只要有“进入”操作,就算合法。(“进入”操作有点插头的感觉)

但是一段路径在中间矩形的长度为 \(len\),那么将贡献 \(len\) 次。

记路径在中间矩形的部分的起点为 \((x,y)\),出点为 \((x',y')\),那么

\[\begin{aligned} len &= y'-y + x'-x + 1\\ &= -(x+y) + (x' + y' + 1) \end{aligned}\]

于是可以拆贡献为起点的贡献和终点的贡献。主要还是根据“只要有进入操作,就算合法”以及“只要有退出操作,就算合法”。

复杂度:\(O(n)\)

关键代码:

inline ll G(int sx, int sy, int fx, int fy) {
  int x = fx - sx, y = fy - sy;
  return get_c(x + y, x);
}

inline void work() {
  int dx[8] = {X1 - 1, X1 - 1, X2, X2, X5, X5, X6 + 1, X6 + 1};
  int dy[8] = {Y1 - 1, Y2, Y1 - 1, Y2, Y5, Y6 + 1, Y5, Y6 + 1};
  int tp[8] = {1, -1, -1, 1, 1, -1, -1, 1};
  ll ans = 0;
  for (int jzp = 0; jzp < 4; ++jzp) {
    int sx = dx[jzp], sy = dy[jzp];
    for (int zzz = 4; zzz < 8; ++zzz) {
      int fx = dx[zzz], fy = dy[zzz];
      ll res = 0;
      int ntp = tp[jzp] * tp[zzz];
      int x, y;
      for (x = X3, y = Y3; x <= X4; ++x) {
        res = (res - G(sx, sy, x, y - 1) * G(x, y, fx, fy) % P * (x + y)) % P;
      }
      for (x = X3, y = Y3; y <= Y4; ++y) {
        res = (res - G(sx, sy, x - 1, y) * G(x, y, fx, fy) % P * (x + y)) % P;
      }
      for (x = X3, y = Y4; x <= X4; ++x) {
        res = (res + G(sx, sy, x, y) * G(x, y + 1, fx, fy) % P * (x + y + 1)) % P;
      }
      for (x = X4, y = Y3; y <= Y4; ++y) {
        res = (res + G(sx, sy, x, y) * G(x + 1, y, fx, fy) % P * (x + y + 1)) % P;
      }
      ans = (ans + ntp * res) % P;
    }
  }
  printf("%lld\n", (ans % P + P) % P);
}
posted @ 2020-09-06 22:05  JiaZP  阅读(130)  评论(1编辑  收藏  举报