题目大意
一棵线段树,分割点任选,每个节点有1个权值。规定:
- 叶节点权值为1
- 右子树线段长度恰好为 k k k 的节点权值为 A A A
- 其他节点权值为 B B B
定义线段树的权值为所有节点权值之积。
定义
f
n
f_n
fn 为区间
[
1
,
n
]
[1,n]
[1,n] 所有可能的线段树的权值和。
给定
k
,
A
,
B
k,A,B
k,A,B,多组询问,每次问
∑
i
=
L
R
f
i
2
\sum_{i=L}^Rf_i^2
∑i=LRfi2 的值(
L
,
R
≤
1
0
7
L,R\le 10^7
L,R≤107)。
思路
其实就是要在
O
(
n
)
O(n)
O(n) 的时间内求出
f
1
∼
f
n
f_1\sim f_n
f1∼fn 的值。
首先不难写出递推式
f
n
=
(
A
−
B
)
f
k
f
n
−
k
+
B
∑
i
=
1
n
−
1
f
i
f
n
−
i
(
i
≥
2
)
f_n=(A-B)f_kf_{n-k}+B\sum_{i=1}^{n-1}f_if_{n-i} (i\ge 2)
fn=(A−B)fkfn−k+Bi=1∑n−1fifn−i(i≥2)
f
1
=
1
f_1=1
f1=1
定义
F
(
x
)
=
∑
i
=
1
∞
f
i
x
i
F(x)=\sum_{i=1}^\infty f_ix^i
F(x)=i=1∑∞fixi
则
F
=
(
A
−
B
)
f
k
x
k
F
+
B
F
2
+
x
F=(A-B)f_kx^kF+BF^2+x
F=(A−B)fkxkF+BF2+x
解得
F
=
−
(
(
A
−
B
)
f
k
x
k
−
1
)
−
(
(
A
−
B
)
f
k
x
k
−
1
)
2
−
4
B
x
2
B
F=\frac{-((A-B)f_kx^k-1)-\sqrt{((A-B)f_kx^k-1)^2-4Bx}}{2B}
F=2B−((A−B)fkxk−1)−((A−B)fkxk−1)2−4Bx
为简化式子,可以先计算出
f
k
=
[
x
k
]
F
(
x
)
=
[
x
k
]
1
−
1
−
4
B
x
2
B
=
(
2
k
−
3
)
!
!
(
2
B
)
k
−
1
k
!
=
1
2
k
−
1
(
2
k
−
1
k
)
B
k
−
1
f_k=[x^k]F(x)=[x^k]\frac{1-\sqrt{1-4Bx}}{2B}=\frac{(2k-3)!!(2B)^{k-1}}{k!}=\frac{1}{2k-1}\binom{2k-1}{k}B^{k-1}
fk=[xk]F(x)=[xk]2B1−1−4Bx=k!(2k−3)!!(2B)k−1=2k−11(k2k−1)Bk−1
令
C
=
(
A
−
B
)
f
k
C=(A-B)f_k
C=(A−B)fk
则
F
=
−
(
C
x
k
−
1
)
−
(
C
x
k
−
1
)
2
−
4
B
x
2
B
F=\frac{-(Cx^k-1)-\sqrt{(Cx^k-1)^2-4Bx}}{2B}
F=2B−(Cxk−1)−(Cxk−1)2−4Bx
但那个根式有点麻烦,因此我们需要尝试进一步化简。
令
Q
=
(
C
x
k
−
1
)
2
−
4
B
x
Q=\sqrt{(Cx^k-1)^2-4Bx}
Q=(Cxk−1)2−4Bx
则
Q
=
1
−
C
x
k
−
2
B
F
Q=1-Cx^k-2BF
Q=1−Cxk−2BF
求导得
Q
′
=
−
k
C
x
k
−
1
−
2
B
F
′
Q'=-kCx^{k-1}-2BF'
Q′=−kCxk−1−2BF′
而对
Q
2
Q^2
Q2 求导得
Q
Q
′
=
k
C
2
x
2
k
−
1
−
k
C
x
k
−
1
−
2
B
QQ'=kC^2x^{2k-1}-kCx^{k-1}-2B
QQ′=kC2x2k−1−kCxk−1−2B
带入
Q
2
Q
′
=
(
Q
Q
′
)
Q
Q^2Q'=(QQ')Q
Q2Q′=(QQ′)Q得
(
C
2
x
2
k
−
2
C
x
k
+
1
−
4
B
x
)
(
k
C
x
k
−
1
+
2
B
F
′
)
+
(
k
C
2
x
2
k
−
1
−
k
C
x
k
−
1
−
2
B
)
(
1
−
C
x
k
−
2
B
F
)
=
0
(C^2x^{2k}-2Cx^k+1-4Bx)(kCx^{k-1}+2BF')+(kC^2x^{2k-1}-kCx^{k-1}-2B)(1-Cx^k-2BF)=0
(C2x2k−2Cxk+1−4Bx)(kCxk−1+2BF′)+(kC2x2k−1−kCxk−1−2B)(1−Cxk−2BF)=0
即得到关于
F
F
F 和
F
′
F'
F′ 的一次式。
整理得
(
C
2
x
2
k
−
2
C
x
k
+
1
−
4
B
x
)
F
′
−
(
k
C
2
x
2
k
−
1
−
k
C
x
k
−
1
−
2
B
)
F
−
(
2
k
−
1
)
C
x
k
−
1
=
0
(C^2x^{2k}-2Cx^k+1-4Bx)F'-(kC^2x^{2k-1}-kCx^{k-1}-2B)F-(2k-1)Cx^k-1=0
(C2x2k−2Cxk+1−4Bx)F′−(kC2x2k−1−kCxk−1−2B)F−(2k−1)Cxk−1=0
取
n
n
n 次项,得
(
n
−
3
k
+
1
)
C
2
f
n
−
2
k
+
1
−
(
2
n
−
3
k
+
2
)
C
f
n
−
k
+
1
+
(
−
4
B
n
+
2
B
)
f
n
+
(
n
+
1
)
f
n
+
1
−
(
2
k
−
1
)
C
[
n
=
=
k
]
=
0
(n-3k+1)C^2f_{n-2k+1}-(2n-3k+2)Cf_{n-k+1}+(-4Bn+2B)f_n+(n+1)f_{n+1}-(2k-1)C[n==k]=0
(n−3k+1)C2fn−2k+1−(2n−3k+2)Cfn−k+1+(−4Bn+2B)fn+(n+1)fn+1−(2k−1)C[n==k]=0
即
f
n
+
1
=
1
n
+
1
(
2
B
(
2
n
−
1
)
f
n
+
(
2
n
−
3
k
+
2
)
C
f
n
−
k
+
1
−
(
n
−
3
k
+
1
)
C
2
f
n
−
2
k
+
1
+
(
2
k
−
1
)
C
[
n
=
=
k
]
)
f_{n+1}=\frac{1}{n+1}(2B(2n-1)f_n+(2n-3k+2)Cf_{n-k+1}-(n-3k+1)C^2f_{n-2k+1}+(2k-1)C[n==k])
fn+1=n+11(2B(2n−1)fn+(2n−3k+2)Cfn−k+1−(n−3k+1)C2fn−2k+1+(2k−1)C[n==k])
即
f
i
=
1
i
(
2
B
(
2
i
−
3
)
f
i
−
1
+
(
2
i
−
3
k
)
C
f
i
−
k
−
(
i
−
3
k
)
C
2
f
i
−
2
k
+
(
2
k
−
1
)
C
[
i
=
=
k
+
1
]
)
f_i=\frac{1}{i}(2B(2i-3)f_{i-1}+(2i-3k)Cf_{i-k}-(i-3k)C^2f_{i-2k}+(2k-1)C[i==k+1])
fi=i1(2B(2i−3)fi−1+(2i−3k)Cfi−k−(i−3k)C2fi−2k+(2k−1)C[i==k+1])
代码
#include <bits/stdc++.h>
#define rep(i, l, r) for (int i = l; i <= r; ++i)
#define per(i, r, l) for (int i = r; i >= l; --i)
using namespace std;
const int mod = 998244353;
const int N = 20000007;
int fac[N], invfac[N];
int _inv[N];
int pw(int x, int y) {
int ret = 1;
while (y) {
if (y & 1) ret = 1ll * ret * x % mod;
x = 1ll * x * x % mod;
y >>= 1;
}
return ret;
}
int inv(int x) { return pw(x, mod - 2); }
void init() {
int lim = 20000000;
fac[0] = 1;
rep(i, 1, lim) { fac[i] = 1ll * fac[i - 1] * i % mod; }
invfac[lim] = inv(fac[lim]);
per(i, lim - 1, 0) { invfac[i] = 1ll * invfac[i + 1] * (i + 1) % mod; }
_inv[1] = 1;
rep(i, 2, lim) { _inv[i] = 1ll * (mod - mod / i) * _inv[mod % i] % mod; }
}
int Comb(int n, int k) {
return 1ll * fac[n] * invfac[k] % mod * invfac[n - k] % mod;
}
int T;
int Q, k, A, B;
int f[N], s[N];
void work() {
f[k] = 1ll * Comb(2 * k - 1, k - 1) * pw(B, k - 1) % mod * _inv[2 * k - 1] %
mod;
int C = 1ll * f[k] * (A - B + mod) % mod;
// printf("C=%d\n", C);
f[1] = 1;
int lim = 10000000;
rep(i, 2, lim) {
int ret = 2ll * B * (2 * i - 3) % mod * f[i - 1] % mod;
if (i > k) {
ret =
(ret + 1ll * (2 * i - 3 * k + mod) * C % mod * f[i - k]) % mod;
}
if (i > 2 * k) {
ret = (ret +
1ll * (3 * k - i + mod) * C % mod * C % mod * f[i - 2 * k]) %
mod;
}
if (i == k + 1) {
ret = (ret + 1ll * (2 * k - 1) * C) % mod;
}
ret = 1ll * ret * _inv[i] % mod;
f[i] = ret;
// if (i <= 100) printf("f[%d]=%d\n", i, f[i]);
}
rep(i, 1, lim) { s[i] = (s[i - 1] + 1ll * f[i] * f[i]) % mod; }
}
int solve(int l, int r) { return (s[r] - s[l - 1] + mod) % mod; }
int main() {
init();
scanf("%d", &T);
while (T--) {
scanf("%d%d%d%d", &Q, &k, &A, &B);
work();
while (Q--) {
int l, r;
scanf("%d%d", &l, &r);
printf("%d\n", solve(l, r));
}
}
return 0;
}