【hdu 7085】Pty loves SegmentTree (推式子)

题目链接

题目大意

一棵线段树,分割点任选,每个节点有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,R107)。

思路

其实就是要在 O ( n ) O(n) O(n) 的时间内求出 f 1 ∼ f n f_1\sim f_n f1fn 的值。
首先不难写出递推式
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=(AB)fkfnk+Bi=1n1fifni(i2)
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=1fixi

F = ( A − B ) f k x k F + B F 2 + x F=(A-B)f_kx^kF+BF^2+x F=(AB)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((AB)fkxk1)((AB)fkxk1)24Bx

为简化式子,可以先计算出
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]2B114Bx =k!(2k3)!!(2B)k1=2k11(k2k1)Bk1
C = ( A − B ) f k C=(A-B)f_k C=(AB)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(Cxk1)(Cxk1)24Bx

但那个根式有点麻烦,因此我们需要尝试进一步化简。

Q = ( C x k − 1 ) 2 − 4 B x Q=\sqrt{(Cx^k-1)^2-4Bx} Q=(Cxk1)24Bx

Q = 1 − C x k − 2 B F Q=1-Cx^k-2BF Q=1Cxk2BF
求导得
Q ′ = − k C x k − 1 − 2 B F ′ Q'=-kCx^{k-1}-2BF' Q=kCxk12BF
而对 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=kC2x2k1kCxk12B
带入 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 (C2x2k2Cxk+14Bx)(kCxk1+2BF)+(kC2x2k1kCxk12B)(1Cxk2BF)=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 (C2x2k2Cxk+14Bx)F(kC2x2k1kCxk12B)F(2k1)Cxk1=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 (n3k+1)C2fn2k+1(2n3k+2)Cfnk+1+(4Bn+2B)fn+(n+1)fn+1(2k1)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(2n1)fn+(2n3k+2)Cfnk+1(n3k+1)C2fn2k+1+(2k1)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(2i3)fi1+(2i3k)Cfik(i3k)C2fi2k+(2k1)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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值