Part 0
由 h i = i × s i h_i=i \times s_i h i = i × s i ,可以发现 $W=h_1\times h_2\times \ldots\times h_n=1 \times s_1 \times 2 \times s_2 \times \ldots \times n \times s_n=(1 \times 2 \times \ldots \times n) \times (s_1\times s_2\times \ldots\times s_n)=n! \times (s_1\times s_2\times \ldots\times s_n)$。
由于 n ≤ 10 7 n \le 10^7 n ≤ 1 0 7 ,阶乘部分可以预处理。下面只讨论如何求 s 1 × s 2 × … × s n s_1\times s_2\times \ldots\times s_n s 1 × s 2 × … × s n 。
Part 1
先来模拟一下样例第 4 4 4 组数据:
i \color{blue}i i
1 \color{blue}1 1
2 \color{blue}2 2
3 \color{blue}3 3
4 \color{blue}4 4
5 \color{blue}5 5
6 \color{blue}6 6
7 \color{blue}7 7
8 \color{blue}8 8
9 \color{blue}9 9
10 \color{blue}10 10
s i s_i s i
6 6 6
3 3 3
2 \color{red}2 2
h i h_i h i
6 6 6
8 8 8
10 10 10
12 12 12
14 14 14
16 16 16
18 18 18
20 20 20
再来模拟一下样例第 5 5 5 组数据:
i \color{blue}i i
1 \color{blue}1 1
2 \color{blue}2 2
3 \color{blue}3 3
4 \color{blue}4 4
5 \color{blue}5 5
6 \color{blue}6 6
7 \color{blue}7 7
8 \color{blue}8 8
9 \color{blue}9 9
10 \color{blue}10 10
11 \color{blue}11 11
12 \color{blue}12 12
13 \color{blue}13 13
14 \color{blue}14 14
15 \color{blue}15 15
16 \color{blue}16 16
17 \color{blue}17 17
18 \color{blue}18 18
19 \color{blue}19 19
20 \color{blue}20 20
21 \color{blue}21 21
22 \color{blue}22 22
23 \color{blue}23 23
s i s_i s i
44 44 44
22 22 22
15 15 15
12 12 12
10 10 10
9 9 9
8 8 8
7 \color{red}7 7
h i h_i h i
44 44 44
45 45 45
48 48 48
50 50 50
54 54 54
56 56 56
63 63 63
70 70 70
77 77 77
84 84 84
91 91 91
98 98 98
105 105 105
112 112 112
119 119 119
126 126 126
133 133 133
140 140 140
147 147 147
154 154 154
161 161 161
Part 2
不难发现,当 s i ≤ i s_i \le i s i ≤ i 时,s i s_i s i 便不再变化了。
证明:
若 s i ≤ i s_i \le i s i ≤ i ,则:
h i = i × s i h_i=i \times s_i
h i = i × s i
h i i + 1 = i × s i i + 1 \dfrac{h_{i}}{i+1}=\dfrac{i \times s_i}{i+1}
i + 1 h i = i + 1 i × s i
s i ≤ i s_i \le i
s i ≤ i
s i − i − 1 ≤ − 1 s_i-i-1 \le -1
s i − i − 1 ≤ − 1
s i − i − 1 < 0 s_i-i-1<0
s i − i − 1 < 0
$$s_i = \dfrac{i \times s_i + s_i}{i+1} > \dfrac{i \times s_i}{i+1}>\dfrac{i \times s_i+s_i-i-1}{i+1}=s_i-1
$$
s i > i × s i i + 1 > s i − 1 s_i>\dfrac{i \times s_i}{i+1}>s_i-1
s i > i + 1 i × s i > s i − 1
s i > h i i + 1 > s i − 1 s_i>\dfrac{h_{i}}{i+1}>s_i-1
s i > i + 1 h i > s i − 1
⌈ h i i + 1 ⌉ = s i \lceil \dfrac{h_{i}}{i+1} \rceil=s_i
⌈ i + 1 h i ⌉ = s i
s i + 1 = s i s_{i+1}=s_i
s i + 1 = s i
故 s i s_i s i 不再变化。
Part 3
此外,当这个时刻到来时,i ≤ 2 a i \le \sqrt{2a} i ≤ 2 a 。
证明:
s i ≤ i s_i \le i s i ≤ i 等价于 h i ≤ i 2 h_i \le i^2 h i ≤ i 2 。设 f ( i ) = h i f(i)=h_i f ( i ) = h i ,g ( i ) = i 2 g(i)=i^2 g ( i ) = i 2 ,d ( i ) = f ( i ) − g ( i ) d(i)=f(i)-g(i) d ( i ) = f ( i ) − g ( i ) ,则 f ( 1 ) = a f(1)=a f ( 1 ) = a ,g ( 1 ) = 1 g(1)=1 g ( 1 ) = 1 ,d ( 1 ) = a − 1 d(1)=a-1 d ( 1 ) = a − 1 ,s i ≤ i s_i \le i s i ≤ i 等价于 d ( i ) ≤ 0 d(i)\le0 d ( i ) ≤ 0 ;
当 i i i 增加 1 1 1 (即设 j = i + 1 j=i+1 j = i + 1 )时,g ( j ) − g ( i ) = 2 j − 1 g(j)-g(i)=2j-1 g ( j ) − g ( i ) = 2 j − 1 ;
显然:
⌈ h i j ⌉ − h i j < 1 \lceil \dfrac{h_{i}}{j} \rceil-\dfrac{h_{i}}{j}<1
⌈ j h i ⌉ − j h i < 1
$$\lceil \dfrac{h_{j-1}}{j} \rceil \times j-\dfrac{h_{i}}{j} \times j<j
$$
h j − h i < j h_j-h_i<j
h j − h i < j
f ( j ) − f ( i ) < j f(j)-f(i)<j
f ( j ) − f ( i ) < j
f ( j ) − f ( i ) ≤ j − 1 f(j)-f(i)\le j-1
f ( j ) − f ( i ) ≤ j − 1
故 $d(j)-d(i)=[f(j)-g(j)]-[f(i)-g(i)]=[f(j)-f(i)]-[g(j)-g(i)]\le (j-1)-(2j-1)=-j$,即 d ( j ) − d ( i ) ≤ − j d(j)-d(i)\le-j d ( j ) − d ( i ) ≤ − j 。
也就是说,当 i i i 增加到 j = i + 1 j=i+1 j = i + 1 时,d d d 函数的值至少减小 j j j ;
当 i = 2 a i=\sqrt{2a} i = 2 a 时,$d(i)=a-1-2-3-\ldots-\sqrt{2a}=a-\dfrac{(1+\sqrt{2a})\times \sqrt{2a}}{2}=-\sqrt{\dfrac{a}{2}}<0$,显然这个时刻已经到来。
Part 4
于是,我们暴力计算 s 1 ∼ s 2 a s_1 \sim s_{\sqrt{2a}} s 1 ∼ s 2 a ,剩下的上快速幂就行了。
最终的时间复杂度为 O ( n + T a ) O(n+T\sqrt{a}) O ( n + T a ) ,空间复杂度为 O ( n ) O(n) O ( n ) 。
提示:代码中 $\lfloor\dfrac{(a+1)\times (i-1)}{i}\rfloor=\lfloor\dfrac{a\times (i-1)+(i-1)}{i}\rfloor=\lceil\dfrac{a\times (i-1)}{i}\rceil$。
Part 5
std:
#include <bits/stdc++.h>
using namespace std;
const int P = 1e9 + 7, N = 1e7 + 12, Real_N = 1e7;
int power(int a, int b, int p)
{
if (b == 1) return a;
int x = power(a, b >> 1, p);
x = 1ll * x * x % p;
if (b & 1) x = 1ll * x * a % p;
return x;
}
int fc[N];
void preset()
{
fc[0] = 1;
for (int i = 1; i <= Real_N; i++)
fc[i] = 1ll * fc[i - 1] * i % P;
}
int main()
{
preset();
int T;
cin >> T;
while (T--)
{
int n, a, i;
cin >> n >> a;
long long W = a;
for (i = 2; i <= n; i++)
{
a = (a + 1) * (i - 1) / i;
W *= a, W %= P;
if (a <= i) break;
}
if (i < n) W *= power(a, n - i, P), W %= P;
cout << W * fc[n] % P << endl;
}
return 0;
}