AGC018E Sightseeing Plan

题目链接 参考博客

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


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

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

点到点

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

点到矩形

[egin{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) ]

矩形到矩形

[egin{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 imes 4) 次计算。

矩形经过矩形到矩形

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

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

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

[egin{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
", (ans % P + P) % P);
}
原文地址:https://www.cnblogs.com/JiaZP/p/13623906.html