多项式全家桶递推版

有的多项式题不需要用到 \(O(n\log n)\) 的多项式全家桶,所以来写下递推的 \(O(n^2)\) 做法。

多项式求逆

\(B(x)\)\(A(x)\) 的逆,那么:

\[\begin{aligned}B(x)A(x)&=[n==0]\\\sum_{i=0}^nA_iB_{n-i}&=0(n>0),B_0=\frac{1}{A_0}(n=0)\\B_n&=-\frac{1}{A_0}\sum_{i=1}^nA_iB_{n-i}\end{aligned} \]

Code

void INV(int *a,int *ans,int n)
{
    for (int i = 0;i <= n;i++)
        ans[i] = 0;
    ans[0] = mypow(a[0],p - 2);
    for (int i = 1;i <= n;i++)
    {
        for (int j = 1;j <= i;i++)
            ans[i] -= 1ll * a[j] * ans[i - j] % p,ans %= p;
        ans[i] = 1ll * ans[i] * ans[0] % p;
    }
}

多项式快速幂

\(B(x)=A^k(x)\) ,那么:

\[\begin{aligned}B'(x)&=kA'(x)A^{k-1}(x)\\B'(x)A(x)&=kA'(x)B(x)\\\sum_{i=0}^nB'_iA_{n-i}&=k\sum_{i=0}^nA'_iB_{n-i}\\\sum_{i=0}^nB_{i+1}(i+1)A_{n-i}&=k\sum_{i=0}A_{i+1}(i+1)B_{n-i}\\B_{n+1}=\frac{k}{A_0(n+1)}&(\sum_{i=0}^nA_{i+1}(i+1)B_{n-i}-\sum_{i=0}^{n-1}B_{i+1}(i+1)A_{n-i})\end{aligned} \]

边界 \(B_0=A_0^k\)

Code

void Polypow(int *a,int *ans,int n,int k)
{
    for (int i = 0;i <= n;i++)
        ans[i] = 0;
    int st = 0,sst = 0;
    while (!a[st])
        st++;
    sst = st;
    st = min(st * k - 1,n);
    if (st == n)
        return;
    st++;
    ans[st] = mypow(a[sst],k);
    int inv = mypow(a[sst],p - 2);
    for (int i = 1;i <= n - st;i++)
    {
        for (int j = 0;j < i;j++)
            ans[i + st] += 1ll * k * a[j + 1 + sst] % p * (j + 1) % p * ans[i - 1 - j + st] % p,ans[i + st] %= p;
        for (int j = 0;j < i - 1;j++)
            ans[i + st] -= 1ll * a[i - 1 - j + sst] * ans[j + 1 + st] % p * (j + 1) % p,ans[i + st] %= p;
        ans[i + st] = 1ll * ans[i + st] * inv % p * Inv[i] % p;
    }
}

Ln

\(B(x)=\ln(A(x))\) ,那么有 \(B'(x)=\frac{A'(x)}{A(x)}\) ,那么:

\[\begin{aligned}A'(x)&=B'(x)A(x)\\A'_n&=\sum_{i=0}^nA_iB'_{n-i}\\A_{n+1}(n+1)&=\sum_{i=0}^nA_iB_{n-i+1}(n-i+1)\\B_{n+1}&=\frac{1}{n+1}(A_{n+1}(n+1)-\sum_{i=1}^nA_iB_{n-i+1}(n-i+1))\end{aligned} \]

要求 \(A_0=1\) ,边界 \(B_0=0\)

Code

void Ln(int *a,int *ans,int n)
{
    for (int i = 0;i <= n;i++)
        ans[i] = 0;
    for (int i = 1;i <= n;i++)
    {
        ans[i] = 1ll * a[i] * i % p;
        for (int j = 1;j < i;j++)
            ans[i] -= 1ll * a[j] * ans[i - j] % p * (i - j) % p,ans[i] %= p;
        ans[i] = 1ll * ans[i] * Inv[i] % p;
    }
}

exp

\(B(x)=e^{A(x)}\) ,那么:

\[\begin{aligned}B'_n&=\sum_{i=0}^nB_iA_{n-i}\\B_{n+1}&=\frac{1}{n+1}\sum_{i=0}^nB_iA_{n-i+1}(n-i+1)\end{aligned} \]

要求 \(A_0=0\) ,边界 \(B_0=1\)

Code

void exp(int *a,int *ans,int n)
{
    for (int i = 0;i <= n;i++)
        ans[i] = 0;
    ans[0] = 1;
    for (int i = 1;i <= n;i++)
    {
        for (int j = 0;j < i;j++)
            ans[i] += 1ll * ans[j] * a[i - j] % p * (i - j) % p,ans[i] %= p;
        ans[i] = 1ll * ans[i] * Inv[i] % p;
    }
}

kexp

\(B(x)=\sum_{i=0}^k\frac{A^i(x)}{i!}\) ,那么:

\[\begin{aligned}B'(x)&=\sum_{i=0}^k\frac{{A^i}'(x)}{i!}\\B'(x)&=\sum_{i=0}^k\frac{A^{i-1}(x)iA'(x)}{i!}\\B'(x)&=A'(x)(B(x)-\frac{A^k(x)}{k!})\end{aligned} \]

\(C(x)=\frac{A^k(x)}{k!}\) ,可以通过多项式快速幂求出,然后就有:

\[\begin{aligned}B'(x)&=A'(x)(B(x)-C(x))\\B'_{n}&=\sum_{i=0}^nA'_{i}(B_{n-i}-C_{n-i})\\B_{n+1}&=\frac{1}{n+1}\sum_{i=0}^nA_{i+1}(i+1)(B_{n-i}-C(n-i))\end{aligned} \]

Code

void kexp(int *a,int *ans,int n,int k)
{
    int inv = 1,res = 1;
    for (int i = 1;i <= k;i++)
        inv = 1ll * inv * i % p;
    inv = mypow(inv,p - 2);
    Polypow(a,tmp,n,k);
    for (int i = 0;i <= n;i++)
        tmp[i] = 1ll * tmp[i] * inv % p;
    for (int i = 0;i <= n;i++)
        ans[i] = 0;
    ans[0] = 1;
    for (int i = 1;i <= k;i++)
    {
        res = 1ll * res * a[0] % p * Inv[i] % p;
        ans[0] += res;
        ans[0] %= p;
    }
    for (int i = 1;i <= n;i++)
    {
        for (int j = 0;j < i;j++)
            ans[i] += 1ll * a[j + 1] * (j + 1) % p * ((ans[i - j - 1] - tmp[i - j - 1]) % p) % p,ans[i] %= p;
        ans[i] = 1ll * ans[i] * Inv[i] % p;
    }
}
posted @ 2021-01-19 19:41  eee_hoho  阅读(131)  评论(0编辑  收藏  举报