从左下矩形出发经过中间矩形的一个点 (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);
}