“停止学习无用的算法,去解决一些问题,学习如何使用二分查找。” – Um_nik
二分查找是一个非常有用的算法,在各种问题中都有应用。以下伪代码展示了二分查找的一种实现方式。函数 BINARYSEARCH 接收两个参数 $A$ 和 $k$,其中 $A = a_1, a_2, \dots, a_n$ 是一个长度为 $n$ 的严格递增整数序列,$k$ 是出现在序列 $A$ 中的一个整数。该函数返回整数 $k$ 在序列 $A$ 中的下标。注意,在以下伪代码中,$\lfloor x \rfloor$ 表示小于或等于 $x$ 的最大整数。
算法 1 二分查找算法
1: function BINARYSEARCH($A, k$)
2: $l \leftarrow 1$
3: $r \leftarrow n$
4: while $l < r$ do
5: $m \leftarrow \lfloor \frac{l+r}{2} \rfloor$
6: if $a_m \ge k$ then
7: $r \leftarrow m$
8: else
9: $l \leftarrow m + 1$
10: end if
11: end while
12: return $l$
13: end function
二分查找的使用有一个前提条件,即被搜索的序列必须是有序的。然而,在本题中,我们将暂时忽略这一约束,研究二分查找在任意序列上的表现。
给定两个整数 $n$ 和 $k$ ($1 \le k \le n$),如果对于 $n$ 的一个排列 $P = p_1, p_2, \dots, p_n$,我们能通过二分查找正确找到整数 $k$ 在排列 $P$ 中的下标,则称该排列 $P$ 是“好的”。换句话说,令 $i = \text{BINARYSEARCH}(P, k)$,若 $p_i = k$,则 $P$ 是好的。
现在我们以相等的概率随机选取一个 $n$ 的排列。计算选取到一个好的排列的概率。
输入格式
输入包含多组测试数据。第一行包含一个整数 $T$ ($1 \le T \le 10^4$),表示测试数据的组数。对于每组测试数据: 第一行包含两个整数 $n$ 和 $k$ ($1 \le k \le n \le 10^9$)。
输出格式
对于每组测试数据,输出一行,包含一个整数,表示选取到一个好的排列的概率,结果对 $(10^9 + 7)$ 取模。
可以证明答案是一个有理数 $\frac{P}{Q}$。你需要输出 $P Q^{-1} \pmod{10^9 + 7}$ 的值,其中 $Q^{-1}$ 是满足 $Q Q^{-1} \pmod{10^9 + 7} = 1$ 的整数。
样例
输入 1
4 3 2 3 1 3 3 1 1
输出 1
500000004 333333336 666666672 1
说明
对于第一个样例测试数据,排列 $\{1, 2, 3\}$、$\{2, 3, 1\}$ 和 $\{3, 1, 2\}$ 都是好的。因此答案是 $\frac{3}{3!} = \frac{1}{2}$。由于 $2 \times 500000004 \pmod{10^9 + 7} = 1$,你应该输出 $1 \times 500000004 \pmod{10^9 + 7} = 500000004$。