@codechef - JADUGAR2@ Chef and Same Old Recurrence 2

Posted tiw-air-oao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了@codechef - JADUGAR2@ Chef and Same Old Recurrence 2相关的知识,希望对你有一定的参考价值。


@description@

定义 dp 序列:

[dp(1) = Kdp(n) = A imes dp(n-1) + B imes sum_{i=1}^{n-1}dp(i) imes dp(n-i)]

Q 次询问,每次询问给出 L, R,求 (sum_{i=L}^{R}dp(i)^2),对 10^9 + 7 取模。

原题戳我查看owo

@solution@

考虑写出生成函数 (F(x) = sum_{i=0}dp(i)x^i),得到:
[F(x) = Ax imes F(x) + B imes F^2(x) + Kx]

解方程得到 (F(x) = frac{(1-Ax)pmsqrt{(1-Ax)^2 - 4KBx}}{2B})。因为 F(x) 常数项为 0,舍弃一个根。有:
[F(x) = frac{(1-Ax)-sqrt{(1-Ax)^2 - 4KBx}}{2B}]

尝试展开得到通项,发现展不开。

注意到当 A = 0 时就是个类似于卡特兰数的数列了,而卡特兰数众所周知有一个递推式子 (f_n = frac{4n-2}{n+1}f_{n-1})
考虑给题目的数列找一个递推式子。首先我们考虑一下怎么通过生成函数得到卡特兰数的递推式子。

-----手动分割线-----

(G(x) = sum_{i=0}f_ix^i),即卡特兰数的生成函数,众所周知 (G(x) = frac{1 - sqrt{1-4x}}{2x})

考虑对 (G(x)) 求导得到 (G'(x) = sum_{i=0}(i+1) imes f_{i+1}x^i),根据求导法则有 (G'(x) = frac{(2x-1)sqrt{1-4x}-4x+1}{8x^3 - 2x^2})

因为 (G(x) = frac{1 - sqrt{1-4x}}{2x}),可以得到 (sqrt{1-4x} = 1 - 2xG(x)),直接代入上式得到 (G'(x) = frac{-2xG(x)+G(x)+1}{4x^2-x})

稍微变形可得 ((4x^2-x)G'(x) + (2x-1)G(x) = 1)

对比等式两边第 n 项的系数(假设 n ≠ 0),有 (4(n-1)f_{n-1} - nf_{n} + 2f_{n-1} - f_{n} = 0)。然后就可以得到 (f_n = frac{4n-2}{n+1}f_{n-1}) 的结果。

-----手动分割线-----

该题也是类似的处理:求出 (F'(x)) 的表达式,用 (F(x)) 表示出根号项并代入 (F'(x)),最后可以得到这样一个结果(过程我就不给了,类似于上面的推导主要是太太太长了不想给):

[(A^2x^2 - (4BK + 2A)x + 1)F'(x) + ((A + 2BK) - A^2x)F(x) = AKx + K]

然后依然是对比第 n 项系数(n > 1),得到 (A^2(n-1) imes dp(n-1) - 2(A + 2BK)n imes dp(n) + (n+1) imes dp(n+1) + (A + 2BK)dp(n) - A^2dp(n-1) = 0)

于是得到递推式 ((n+1)dp(n+1) = (2n - 1)(A + 2BK)dp(n) - A^2(n-2)dp(n-1))

(dp(n) = frac{(2n - 3)(A + 2BK)dp(n) - A^2(n-3)dp(n-2)}{n})

然后就没了。直接 O(N) 预处理。

@accepted code@

#include <cstdio>

const int MAXN = 10000000;
const int MOD = int(1E9) + 7;
int add(int a, int b) {return a + b >= MOD ? a + b - MOD : a + b;}
int sub(int a, int b) {return a - b < 0 ? a - b + MOD : a - b;}
int mul(int a, int b) {return 1LL*a*b%MOD;}

int N, K, A, B, Q;
    
int f[MAXN + 5], inv[MAXN + 5];
void init() {
    inv[1] = 1;
    for(int i=2;i<=N;i++)
        inv[i] = (MOD - 1LL*(MOD/i)*inv[MOD%i]%MOD);
    
    int p = add(A,mul(2*K,B)), q = mul(A,A);
    f[1] = K, f[2] = mul(K,add(A,mul(B,K)));
    for(int i=3;i<=N;i++)
        f[i] = mul(inv[i],sub(mul(mul(p,2*i-3),f[i-1]),mul(mul(q,i-3),f[i-2])));
    
    for(int i=1;i<=N;i++) f[i] = add(f[i-1],mul(f[i],f[i]));
}

int main() {
    scanf("%d%d%d%d", &N, &K, &A, &B), init();
    scanf("%d", &Q);
    for(int i=1;i<=Q;i++) {
        int L, R; scanf("%d%d", &L, &R);
        printf("%d
", sub(f[R], f[L-1]));
    }
}

@details@

查了很久都没有查到卡特兰数的递推公式的生成函数证法(甚至翻到了wiki上去都没有。。。)。

一看题解,woc 还有求导这种操作。

早知道就不花几个晚上思考了。。。直接翻题解不挺好的。。。

以上是关于@codechef - JADUGAR2@ Chef and Same Old Recurrence 2的主要内容,如果未能解决你的问题,请参考以下文章

Codechef 虫洞:我的逻辑有啥问题?

Codechef RIN 「Codechef14DEC」Course Selection 最小割离散变量模型

codechef Suffix Palindromes

IDE 中的代码正确,但 CodeChef 中出现错误

Codechef Course Selection

CodeChef CBAL