那么用四元组 (dr,dc,r,c) 表示一个机器人的位置和方向。又因为 dr 和 dc 只有 4 种不同的可能,
则如果两次机器人的位置和方向对应四元组完全相等,则两次以后的所有行动也都完全相等,
这样就产生了一个循环节。
而两两不完全相同的四元组最多有 4nm 个,故循环节长度不超过 4nm。
那么我们记一个循环节中,机器人第 i 次有机会覆盖到特殊点时,数 t_i 等于:
从这个循环节的起点到当前机器人所在位置,机器人走的步数。
定义机器人在某个位置 (r,c) 时有机会覆盖到特殊点,当且仅当 r=r_d 或 c=c_d。
我们再记最终答案为 T,不覆盖的概率 q=1-p,循环节长度为 z,
一个循环节中有 k 个位置使得机器人有机会覆盖到特殊点,则我们有:
含义是:
从某一个循环节开始,我们第一次有 $p$ 的概率覆盖特殊点,这时一共走了 $t_1$ 步;
同时,我们有 $q=1-p$ 的概率不覆盖特殊点,我们就需要继续走,
直到我们第二次有机会覆盖特殊点,我们又有 $p$ 的概率覆盖特殊点,这时我们一共走了 $t_2$ 步,
我们也有 $q$ 的概率不覆盖特殊点,我们就又需要继续走,这样的过程一直进行,
一直到我们第 $k$ 次有机会覆盖特殊点,此时我们有 $p$ 的概率覆盖特殊点,这时一共走了 $t_k$ 步,
我们同样有 $q$ 的概率不覆盖特殊点,我们就又需要继续走,
这时我们走完了一个循环节,已经走了 $z$ 步后进入下一个循环节,
而下一个循环节,在加上一个循环节的 $z$ 步后,就和上面的过程相似了。
我们发现,既然下一个循环节的过程和这个循环节相似,
那么,在减掉这个及之前的循环节所走的步数后,下一个循环节的答案还是 $T$。
那么我们也许可以尝试用答案 $T$ 去表达自己,即:
$T=pt_1+q(pt_2+q(pt_3+q(\cdots q(pt_k+q(z+T))\cdots)))$。
写成和式的形式,就是:
$T=(\sum\limits_{i=1}^{k}q^{i-1}pt_i)+q^{k}(z+T)$。
这个就很像一个关于 $T$ 的方程,我们解一下就可以得到:
$(1-q^k)T=(\sum\limits_{i=1}^{k}q^{i-1}pt_i)+q^{k}z$,即 $T=\frac{(\sum\limits_{i=1}^{k}q^{i-1}pt_i)+q^{k}z}{1-q^k}$。
因为模数是质数,所以我们只需要处理逆元后就可以算了。
时间复杂度是 $O(k)$ 的,而 $k\leq z\leq 4nm$,故可以通过。
当然,我写的代码里用了 STL map 记录一个四元组是否出现过,
这样比较方便,但复杂度就带了 $\log$,而实际上可以直接用数组记录,复杂度就是线性。
```
#define mp make_pair
#define int long long
#define pii pair < int , int >
#define rep(i, a, b) for (int i = (a); i <= (b); i++)
// 快读就不放了
const int N (1e6 + 10);
const int mod (1e9 + 7);
int ksm (int a, int b) {
int r = 1;
for (; b; a = a * a % mod, b >>= 1) if (b & 1) r = r * a % mod;
return r;
}
int t[N];
map < pair < pii, pii > , int > vis;
int n, m, k, rb, cb, rd, cd, p, P, q, z;
void work() {
vis.clear();
n = read(), m = read(), rb = read(), cb = read();
rd = read(), cd = read(), P = read();
p = P * ksm (100, mod - 2) % mod, q = (mod + 1 - p) % mod;
int dr = 1, dc = 1;
k = z = 0;
if (rb + dr > n || rb + dr <= 0) dr = -dr;
if (cb + dc > m || cb + dc <= 0) dc = -dc;
for (int i = 0; ; i++) {
vis[mp (mp (rb, cb), mp (dr, dc))] = 1;
if (cd == cb || rd == rb) t[++k] = i;
rb += dr, cb += dc, z++;
if (rb + dr > n || rb + dr <= 0) dr = -dr;
if (cb + dc > m || cb + dc <= 0) dc = -dc;
if (vis.count (mp (mp (rb, cb), mp (dr, dc)))) break;
}
int inv = mod + 1 - ksm (q, k);
inv %= mod, inv = ksm (inv, mod - 2);
int ans = z * ksm (q, k) % mod * inv % mod;
rep (i, 1, k)
ans = (ans + (t[i] * p % mod * inv % mod * ksm (q, i - 1) % mod) % mod) % mod;
cout << ans << endl;
}
signed main() {
int t = read();
while (t--) work();
return 0;
}
```