反射容斥
反射容斥
单直线问题:
每次只能向上走一格或向右走一格,求不碰到 \(y=x+b\) 从 \((0,0)\) 走到 \((s,t)\) 的方案数。

如图就是一条错误的路线。
考虑将终点沿这条直线翻折:

发现每一条错误的路线都唯一对应一条从 \((0,0)\) 走到 \((s-b,t+b)\) 的路线(就是原点到翻折后的点)。
求从原点走到某个点的方案数是容易的:即在一共 \(s+t\) 步中选择 \(s\) 步往右走,其他 \(t\) 步往上走。或是在 \(s+t\) 步中选择 \(t\) 步往上走,其他 \(s\) 步往右走,这两者数学上本来也是等价的。
所以答案就是:
双直线问题:
这是本文的重点。
现有两条直线 \(A:y=x+a,B=y=x+b\) 。求不碰到 \(A,B\) 从 \((0,0)\) 走到 \((s,t)\) 的方案数。
一个大致的想法是,算出碰到直线 \(A\) 的方案数 \(f(A)\) ,以及碰到直线 \(B\) 的方案数 \(f(B)\) 。
然后:
但难就难在算出同时碰到 \(AB\) 的方案数。
我们可以进行如下考虑:
先将 \((s,t)\) 沿 \(B\) 翻折得到绿点 \((t-b,s+b)\) ,这样从 \((0,0)\) 到 \((t-b,s+b)\) 的绿色路线就都碰到了 \(B\) 。
那么如果还要碰到 \(A\) 的话,就需要绿色线碰到翻折过后的 \(A\) ,(蓝色线)。
那么将绿点继续沿蓝色线翻折得到黄色点 \((s+a-b,t-a+b)\) 。
这样从 \((0,0)\) 到 \((s+a-b,t-a+b)\) 的线就经过了 \(A,B\) 。
但是聪明的你一定会发现这样会统计漏:
如果在第一次碰到 \(B\) 之前我碰到了 \(A\) 那我就不用要求后半段碰到 \(A\) 了。
所以我们可以把刚刚的做法对 \(A\) 直线同样做一次:
先将 \((s,t)\) 沿 \(A\) 翻折得到 \((t-a,s+a)\) ,这样从 \((0,0)\) 到 \((t-a,s+a)\) 的路线就都碰到了 \(A\) 。
那么如果还要碰到 \(B\) 的话,就需要这条路线碰到翻折过后的 \(B\) 。
\(.....\)
不妨把第一次的结果记为 \(f(BA)\) (先经过 \(B\) ,再经过 \(A\) ),第二次记为 \(f(AB)\) (先经过 \(A\) ,再经过 \(B\)) 。
然后我们考虑这样真的就做完了吗?
并没有。
因为这样会算重。
如果某条路线先经过了 \(A\) ,然后是 \(B\) ,然后又经过了 \(A\) 。那么 \(f(AB)\) 和 \(f(BA)\) 都会把它算一次。
同理,如果某条路线先经过了 \(B\) ,然后是 \(A\) ,然后又经过了 \(B\) 。那么 \(f(AB)\) 和 \(f(BA)\) 也都会把它算一次。
所以,我们必须减去这两者的方案数。
当然这就是 \(f(ABA)\) 和 \(f(BAB)\) 。
相信你也发现了,这样 \(ABAB\) 和 \(BABA\) 还会算重,所以我们继续容斥掉这两者。
所以这是一个递归下去的问题。
而我们知道 \(f\) 的值是很好算的(就是类似上面的,不断翻折几次)。
而且这个式子只有有限项,因为后面点的坐标会被越翻越离开一象限,导致对应 \(f\) 的值为 \(0\) ,没有统计的必要。
以 \(f(A...)\) 为例:
此时:
-
\(A\) : \((t-a,s+a)\)
-
\(AB\) : \((s+b-a,t-b+a)\)
-
\(ABA\) : \((t-2a+b,s+2a-b)\)
-
\(ABAB\) : \((s+2b-2a,t-2b+2a)\)
上述例子已经说明,在有限项后,该点的横坐标会小于 \(0\) ,此时方案数为 \(0\) ,对应的 \(f\) 为 \(0\) 。
时间复杂度:

浙公网安备 33010602011771号