多项式求逆
给定一个 \(n-1\) 次的多项式 \(A(x)(a_0 \neq 0)\) ,要求一个多项式 \(F(x)\) 满足 \(F(x)A(x) \equiv 1 \pmod x^n\) 。
假设求出了 \(F_0(x)\) 满足 \(F_0(x)A(x) \equiv 1 \pmod{x^{\lceil \frac{n}{2} \rceil}}\) ,那么有
由于 \(A(x) \neq 0\) ,所以
又因为 \(F(x)A(x) \equiv 1 \pmod{x^n}\) ,两边都乘个 \(A(x)\) ,
所以我们可以递归求解,时间复杂度 \(T(n) = T(n/2)+n\log n = n\log n\) 。
void get_inv(int *a, int *f, int n){
if(n == 1)return f[0] = fpow(a[0], mod-2), void();
get_inv(a, f, n+1>>1), init(2*n-1);//init()处理数组长度和蝴蝶变换
fp(i, 0, n-1)inv_ary[i] = a[i];
ntt(f, 0), ntt(inv_ary, 0);
fp(i, 0, lim-1)f[i] = 1ll*f[i]*(2-1ll*f[i]*inv_ary[i]%mod+mod)%mod;
ntt(f, 1);
fp(i, n, lim-1)f[i] = 0;
fp(i, 0, lim-1)inv_ary[i] = 0;
}
多项式求 \(\rm{ln}\) 。
给定一个 \(n-1\) 次的多项式 \(A(x)(a_0 = 1)\) ,要求一个多项式 \(F(x)\) 满足 \(F(x) \equiv \ln A(x) \pmod{x^n}\) 。
两边求个导得到:
所以只需要对 \(A(x)\) 求个导和逆就能求出 \(F'(x)\) 了。最后再对 \(F'(x)\) 求个积分,由于 \(a_0=1\) ,所以常数项为 \(0\) 。时间复杂度为 \(\mathcal{O} (n\log n)\) 。
void get_ln(int *a, int *f, int n){
get_inv(a, ln_ary, n), init(2*n-2);
fp(i, 1, n-1)f[i-1] = 1ll*a[i]*i%mod;
ntt(f, 0), ntt(ln_ary, 0);
fp(i, 0, lim-1)f[i] = 1ll*f[i]*ln_ary[i]%mod;
ntt(f, 1);
fp(i, n-1, lim)f[i] = 0;
fp(i, 0, lim)ln_ary[i] = 0;
fb(i, n-1, 1)f[i] = 1ll*f[i-1]*inv[i]%mod;
f[0] = 0;
}
牛顿迭代
给定一个函数 \(G(x)\) ,要求一个多项式 \(F(x)\) 满足 \(G(F(x)) \equiv 0 \pmod{x^n}\) 。
假设求出了 \(F_0(x)\) 满足 \(G(F_0(x)) \equiv 0 \pmod{x^{\lceil \frac{n}{2}\rceil}}\) ,那么把 \(G(x)\) 在 \(F_0(x)\) 处泰勒展开可以得到:
因为 \(F(x)-F_0(x)\) 最低次是 \(x^{\lceil \frac{n}{2}\rceil}\) ,所以从第三项开始模 \(x^n\) 就为 \(0\) 了。 注意这里的求导是求 \(F_0(x)\) 的偏导 。然后就可以递归计算了。
多项式 \(\rm{exp}\)
给定一个 \(n-1\) 次多项式 \(A(x)(a_0=0)\) ,要求一个多项式 \(F(x)\) 满足 \(F(x) \equiv e^{A(x)} \pmod{x^n}\) 。
两边求个 \(\ln