题意
求
∑
i
=
1
n
∑
j
=
1
i
∑
k
=
1
j
gcd
(
(
i
−
j
)
!
,
(
j
−
k
)
!
)
\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{i}\sum\limits_{k=1}^{j}\gcd((i-j)!,(j-k)!)
i=1∑nj=1∑ik=1∑jgcd((i−j)!,(j−k)!)
T
T
T 组数据。
T
,
n
≤
1
0
6
T,n\le 10^6
T,n≤106。
题解
易得
a
n
s
=
∑
i
=
1
n
∑
j
=
1
i
∑
k
=
1
j
min
(
i
−
j
,
j
−
k
)
!
ans =\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{i}\sum\limits_{k=1}^{j}\min(i-j,j-k)!
ans=i=1∑nj=1∑ik=1∑jmin(i−j,j−k)!
记
x
=
i
−
j
,
y
=
j
−
k
x=i-j,y=j-k
x=i−j,y=j−k。显然
x
,
y
≥
0
,
x
+
y
=
i
−
k
≤
n
−
1
x,y\ge 0,x+y=i-k\le n-1
x,y≥0,x+y=i−k≤n−1。
那么 0 ≤ min ( x , y ) ≤ ⌊ n − 1 2 ⌋ 0\le \min(x,y)\le \lfloor\frac{n-1}{2}\rfloor 0≤min(x,y)≤⌊2n−1⌋。
考虑枚举
d
=
min
(
x
,
y
)
d=\min(x,y)
d=min(x,y),计算对于每个
d
d
d 有多少种
i
,
j
,
k
i,j,k
i,j,k 的取值方案
c
n
t
d
cnt_d
cntd。
a
n
s
=
∑
d
=
0
⌊
n
−
1
2
⌋
d
!
⋅
c
n
t
d
ans=\sum\limits_{d=0}^{\lfloor\frac{n-1}{2}\rfloor}d!\cdot cnt_d
ans=d=0∑⌊2n−1⌋d!⋅cntd
对于一组确定的
x
,
y
x,y
x,y,若我们能确定
k
k
k 的值,那么有
j
=
y
+
k
,
i
=
x
+
j
=
x
+
y
+
k
j=y+k,i=x+j=x+y+k
j=y+k,i=x+j=x+y+k,也就是确定一个
k
k
k 即可确定一组
i
,
j
,
k
i,j,k
i,j,k。因为
i
≤
n
i\le n
i≤n,所以
x
+
y
+
k
≤
n
x+y+k\le n
x+y+k≤n,所以
k
≤
n
−
x
−
y
k\le n-x-y
k≤n−x−y。即对于一组确定的
x
,
y
x,y
x,y,有
n
−
x
−
y
n-x-y
n−x−y 组
i
,
j
,
k
i,j,k
i,j,k 与之对应。
考虑对于确定的 d d d,有多少组 x , y x,y x,y。不妨假设 x = d x=d x=d,则 y y y 显然满足 y ≥ d y\ge d y≥d,因为 x + y ≤ n − 1 x+y\le n-1 x+y≤n−1,所以 d ≤ y ≤ n − x − 1 d\le y\le n-x-1 d≤y≤n−x−1,所以 y y y 有 n − x − 1 − d + 1 = n − x − d = n − 2 d n-x-1-d+1=n-x-d=n-2d n−x−1−d+1=n−x−d=n−2d 种取值。那么对于所有的 d d d,当 x = d x=d x=d 时总共的方案为 ∑ d n − 2 d = ( n − 2 d + 1 ) ( n − 2 d ) 2 \sum\limits_{d} n-2d=\dfrac{(n-2d+1)(n-2d)}{2} d∑n−2d=2(n−2d+1)(n−2d)。 x x x 取 d d d 与 y y y 取 d d d 的方案是一样的,所以直接乘 2 2 2。注意这里对于 x = y = d x=y=d x=y=d 的方案算了两次,减去 n − 2 d n-2d n−2d 即可。
现在有
c
n
t
d
=
2
⋅
(
n
−
2
d
+
1
)
(
n
−
2
d
)
2
−
(
n
−
2
d
)
=
(
n
−
2
d
)
2
cnt_d=2\cdot\dfrac{(n-2d+1)(n-2d)}{2}-(n-2d)=(n-2d)^2
cntd=2⋅2(n−2d+1)(n−2d)−(n−2d)=(n−2d)2
所以现在有
a
n
s
=
∑
d
=
0
⌊
n
−
1
2
⌋
d
!
⋅
(
n
−
2
d
)
2
ans=\sum\limits_{d=0}^{\lfloor\frac{n-1}{2}\rfloor}d!\cdot (n-2d)^2
ans=d=0∑⌊2n−1⌋d!⋅(n−2d)2
看起来现在可以
O
(
T
n
)
O(Tn)
O(Tn) 解决这个问题了。
只需要再进一步推导:
a
n
s
=
∑
d
=
0
⌊
n
−
1
2
⌋
(
n
2
d
!
−
d
!
4
n
d
+
d
!
4
d
2
)
=
n
2
∑
d
=
0
⌊
n
−
1
2
⌋
d
!
−
4
n
∑
d
=
0
⌊
n
−
1
2
⌋
d
!
⋅
d
+
4
∑
d
=
0
⌊
n
−
1
2
⌋
d
!
⋅
d
2
ans=\sum\limits_{d=0}^{\lfloor\frac{n-1}{2}\rfloor}(n^2d!-d!4nd+d!4d^2)\\ =n^2\sum\limits_{d=0}^{\lfloor\frac{n-1}{2}\rfloor}d!-4n\sum\limits_{d=0}^{\lfloor\frac{n-1}{2}\rfloor}d!\cdot d+4\sum\limits_{d=0}^{\lfloor\frac{n-1}{2}\rfloor}d!\cdot d^2
ans=d=0∑⌊2n−1⌋(n2d!−d!4nd+d!4d2)=n2d=0∑⌊2n−1⌋d!−4nd=0∑⌊2n−1⌋d!⋅d+4d=0∑⌊2n−1⌋d!⋅d2
于是只需要预处理三个
∑
\sum
∑ 的前缀和就能
O
(
1
)
O(1)
O(1) 询问啦。总时间复杂度
O
(
n
+
T
)
O(n+T)
O(n+T)。
实现
注意阶乘求和不要忘了
0
0
0 的阶乘。long long
要开够。
然鹅我把 ⌊ n − 1 2 ⌋ \lfloor\frac{n-1}{2}\rfloor ⌊2n−1⌋ 写成了 ⌊ n 2 ⌋ \lfloor\frac{n}{2}\rfloor ⌊2n⌋ 竟然还过了。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1000005;
const LL mod = 10086001;
int T;
LL f1[N], f2[N], sf[N], n;
void init() {
sf[0] = 1;
for (LL i = 1, fac = 1; i < (N >> 1); i++, fac = fac * i % mod)
sf[i] = (sf[i - 1] + fac) % mod,
f1[i] = (f1[i - 1] + i * i % mod * fac) % mod,
f2[i] = (f2[i - 1] + i * fac) % mod;
}
int main() {
init();
scanf("%d", &T);
while (T--)
scanf("%lld", &n),
printf("%lld\n", ((n * n % mod * sf[(n - 1) >> 1] % mod + 4 * f1[(n - 1) >> 1] % mod - 4 * n * f2[(n - 1) >> 1] % mod) % mod + mod) % mod);
return 0;
}
总结
- 这题只要敢推式子就能做。思路非常明显。