多项式基础II 多项式求逆 多项式取模 多项式开方 多项式牛顿迭代 多项式ln 多项式exp

7 篇文章 0 订阅
5 篇文章 0 订阅

多项式求逆

已知 f ( x ) f(x) f(x),要求出 g ( x ) g(x) g(x)满足 f ( x ) g ( x ) ≡ 1 ( m o d x n ) f(x)g(x)\equiv 1\pmod {x^n} f(x)g(x)1(modxn)
其中模 x n x^n xn的意义是将指数大于等于 n n n的部分都去掉。

n n n向上扩充为 2 k − 1 2^k-1 2k1。假设我们已求出 g ′ ( x ) g'(x) g(x)满足 f ( x ) g ′ ( x ) ≡ 1 ( m o d x n 2 ) f(x)g'(x)\equiv 1\pmod{x^\frac{n}{2}} f(x)g(x)1(modx2n)
显然在模 x n x^n xn成立的条件在模 x n 2 x^\frac{n}{2} x2n时也成立。于是上两式相减得 f ( x ) ( g ( x ) − g ′ ( x ) ) ≡ 0 ( m o d x n 2 ) f(x)(g(x)-g'(x))\equiv 0\pmod{x^\frac{n}{2}} f(x)(g(x)g(x))0(modx2n)
由于 f ( x ) ̸ ≡ 0 f(x)\not\equiv0 f(x)̸0,因此 g ( x ) − g ′ ( x ) ≡ 0 ( m o d x n 2 ) g(x)-g'(x)\equiv 0\pmod{x^\frac{n}{2}} g(x)g(x)0(modx2n)
两边平方得 g 2 ( x ) − 2 g ( x ) g ′ ( x ) + g ′ 2 ( x ) ≡ 0 ( m o d x n ) g^2(x)-2g(x)g'(x)+g'^2(x)\equiv 0\pmod{x^n} g2(x)2g(x)g(x)+g2(x)0(modxn)
两边同乘 f ( x ) f(x) f(x) g ( x ) − 2 g ′ ( x ) + f ( x ) g ′ 2 ( x ) ≡ 0 ( m o d x n ) g(x)-2g'(x)+f(x)g'^2(x)\equiv 0\pmod{x^n} g(x)2g(x)+f(x)g2(x)0(modxn)
于是 g ( x ) ≡ 2 g ′ ( x ) − f ( x ) g ′ 2 ( x ) ( m o d x n ) g(x)\equiv 2g'(x)-f(x)g'^2(x)\pmod{x^n} g(x)2g(x)f(x)g2(x)(modxn)
用FFT计算,递归求解即可。总时间复杂度为 O ( n log ⁡ n ) O(n\log n) O(nlogn)

口诀:减去平成(2019.2.7)

inline pol inv(pol g) {
    int n = g.size(), m = n >> 1;
    if(n == 1) return unipol(inv(g[0]));
    pol f0 = g; f0.resize(m);
    f0 = inv(f0);
    f0.resize(n<<1); g.resize(n<<1);
    ntt(f0, 1); ntt(g, 1);
    for(int i = 0; i < n<<1; i++) g[i] = mul(f0[i], sub(2, mul(g[i], f0[i])));
    ntt(g, 0); g.resize(n);
    return g;
}

多项式取模(多项式带余除法)

给定 f ( x ) f(x) f(x) g ( x ) g(x) g(x),要求 q ( x ) q(x) q(x) r ( x ) r(x) r(x)满足
f ( x ) = g ( x ) q ( x ) + r ( x ) f(x)=g(x)q(x)+r(x) f(x)=g(x)q(x)+r(x)
f ( x ) f(x) f(x)的阶为 n − 1 n-1 n1 g ( x ) g(x) g(x)的阶为 m − 1 m-1 m1,则 q ( x ) q(x) q(x)的阶为 n − m n-m nm r ( x ) r(x) r(x)的阶小于 m − 1 m-1 m1

f ( x ) f(x) f(x) r ( x ) r(x) r(x)的系数在 [ 0 , n − 1 ] [0,n-1] [0,n1]内翻转, g ( x ) g(x) g(x)的系数在 [ 0 , m − 1 ] [0,m-1] [0,m1]内翻转, q ( x ) q(x) q(x)的系数在 [ 0 , n − m ] [0,n-m] [0,nm]内翻转。以下标 r r r表示翻转,则同样有 f r ( x ) = g r ( x ) q r ( x ) + r r ( x ) f_r(x)=g_r(x)q_r(x)+r_r(x) fr(x)=gr(x)qr(x)+rr(x)
由于 r ( x ) r(x) r(x)的指数范围是 [ 0 , m − 2 ] [0,m-2] [0,m2],因而 r r ( x ) r_r(x) rr(x)的指数范围是 [ n − m + 1 , n − 1 ] [n-m+1,n-1] [nm+1,n1]。因此
f r ( x ) ≡ g r ( x ) q r ( x ) ( m o d x n − m + 1 ) f_r(x)\equiv g_r(x)q_r(x)\pmod{x^{n-m+1}} fr(x)gr(x)qr(x)(modxnm+1) q r ( x ) ≡ f r ( x ) g r ( x ) − 1 ( m o d x n − m + 1 ) q_r(x)\equiv f_r(x)g_r(x)^{-1}\pmod{x^{n-m+1}} qr(x)fr(x)gr(x)1(modxnm+1)
由于 q r ( x ) q_r(x) qr(x)的指数范围是 [ 0 , n − m ] [0,n-m] [0,nm],模 x n − m + 1 x^{n-m+1} xnm+1对其不产生影响。于是可由此直接得到 q ( x ) q(x) q(x)

inline pol dvd(pol a, pol b) {
	int n = a.size(), m = b.size();
	if(n < m) return unipol(0);
	reverse(a.begin(), a.end());
	reverse(b.begin(), b.end());
	b.resize(ext(n-m+1));
	b = inv(b);
	a.resize(n-m+1);
	a = a * b;
	a.resize(n-m+1);
	reverse(a.begin(), a.end());
	return a;
}

多项式开方

g ( x ) g(x) g(x)满足 g 2 ( x ) ≡ f ( x ) ( m o d x n ) g^2(x)\equiv f(x)\pmod{x^n} g2(x)f(x)(modxn)

假设已求出 g ′ ( x ) g&#x27;(x) g(x)满足 g ′ 2 ( x ) ≡ f ( x ) ( m o d x n 2 ) g&#x27;^2(x)\equiv f(x)\pmod{x^\frac{n}{2}} g2(x)f(x)(modx2n),则 g ′ 2 ( x ) − g 2 ( x ) ≡ 0 ( m o d x n 2 ) g&#x27;^2(x)-g^2(x)\equiv 0\pmod{x^\frac{n}{2}} g2(x)g2(x)0(modx2n) ( g ′ ( x ) + g ( x ) ) ( g ′ ( x ) − g ( x ) ) ≡ 0 ( m o d x n 2 ) (g&#x27;(x)+g(x))(g&#x27;(x)-g(x))\equiv 0\pmod{x^\frac{n}{2}} (g(x)+g(x))(g(x)g(x))0(modx2n) g ′ ( x ) − g ( x ) ≡ 0 ( m o d x n 2 ) g&#x27;(x)-g(x)\equiv 0\pmod{x^\frac{n}{2}} g(x)g(x)0(modx2n)
两边平方得 g 2 ( x ) − 2 g ( x ) g ′ ( x ) + g ′ 2 ( x ) ≡ 0 ( m o d x n ) g^2(x)-2g(x)g&#x27;(x)+g&#x27;^2(x)\equiv 0\pmod{x^n} g2(x)2g(x)g(x)+g2(x)0(modxn)
于是 g ( x ) ≡ f ( x ) + g ′ 2 ( x ) 2 g ′ ( x ) ( m o d x n ) g(x)\equiv\frac{f(x)+g&#x27;^2(x)}{2g&#x27;(x)}\pmod{x^n} g(x)2g(x)f(x)+g2(x)(modxn)
递归求解即可。注意如果取模,计算常数项时应用二次剩余。

int inv2 = inv(2);

inline pol sqt(pol g) {
	int n = g.size(), m = n >> 1;
	if(n == 1) return unipol(msqrt(1));
	pol g0 = g; g0.resize(m);
	pol f0 = sqt(g0), invf0 = f0;
	invf0.resize(n);
	for(int i = 0; i < n; i++) invf0[i] = mul(invf0[i], 2);
	invf0 = inv(invf0);
	f0 = f0 * f0;
	for(int i = 0; i < n; i++) Add(g[i], f0[i]);
	g = g * invf0;
	g.resize(n);
	return g;
}

现在你已经可以做小朋友与二叉树了。

11.19 here


多项式求对数

ln ⁡ f ( x ) ( m o d x n ) \ln f(x)\pmod {x^n} lnf(x)(modxn)

ln ⁡ f ( x ) ≡ ∫ ( ln ⁡ f ( x ) ) ′ ≡ ∫ f ( x ) ′ f ( x ) ( m o d x n ) \ln f(x)\equiv \int(\ln f(x))&#x27;\equiv \int\frac{f(x)&#x27;}{f(x)}\pmod{x^n} lnf(x)(lnf(x))f(x)f(x)(modxn)。用多项式求导、多项式积分和多项式求逆即可。

inline pol ln(pol g) {
    int n = g.size();
    pol gg; gg.resize(n);
    for(int i = 0; i < n-1; i++) gg[i] = mul(i+1, g[i+1]);
    gg[n-1] = 0;
    pol f = inv(g); f.resize(n<<1); gg.resize(n<<1);
    ntt(f, 1); ntt(gg, 1); 
    for(int i = 0; i < n<<1; i++) gg[i] = mul(gg[i], f[i]);
    ntt(gg, 0);
    for(int i = 1; i < n; i++) g[i] = mul(inv(i), gg[i-1]);
    g[0] = 0; 
    return g;
}

多项式牛顿迭代

给定 g ( f ( x ) ) g(f(x)) g(f(x)),求其零点(即求一个 f ( x ) f(x) f(x)使 g ( f ( x ) ) ≡ 0 ( m o d x n ) g(f(x))\equiv 0\pmod {x^n} g(f(x))0(modxn))。

多项式上的牛顿迭代公式 f 0 ( x ) ≡ f ( x ) &VeryThinSpace; m o d &VeryThinSpace; x n 2 ( m o d x n ) f_0(x)\equiv f(x)\bmod x^\frac{n}{2}\pmod{x^n} f0(x)f(x)modx2n(modxn),则有 f ( x ) ≡ f 0 ( x ) − g ( f 0 ( x ) ) g ′ ( f 0 ( x ) ) ( m o d x n ) f(x)\equiv f_0(x)-\frac{g(f_0(x))}{g&#x27;(f_0(x))}\pmod{x^n} f(x)f0(x)g(f0(x))g(f0(x))(modxn)
递归解决即可。注意每次问题规模减半,每层复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn),因此总复杂度为 O ( n log ⁡ n ) O(n\log n) O(nlogn)

多项式exp

f ( x ) ≡ e h ( x ) ( m o d x n ) f(x)\equiv e^{h(x)}\pmod {x^n} f(x)eh(x)(modxn)

两边取对数得 ln ⁡ f ( x ) ≡ h ( x ) ( m o d x n ) \ln f(x)\equiv h(x)\pmod{x^n} lnf(x)h(x)(modxn)
g ( f ( x ) ) ≡ ln ⁡ f ( x ) − h ( x ) ( m o d x n ) g(f(x))\equiv \ln f(x)-h(x)\pmod{x^n} g(f(x))lnf(x)h(x)(modxn),则问题变为求该函数的零点。由多项式上的牛顿迭代公式,有 f ( x ) ≡ f 0 ( x ) − ln ⁡ f 0 ( x ) − h ( x ) 1 f 0 ( x ) ( m o d x n ) f(x)\equiv f_0(x)-\frac{\ln f_0(x)-h(x)}{\frac{1}{f_0(x)}}\pmod{x^n} f(x)f0(x)f0(x)1lnf0(x)h(x)(modxn) f ( x ) ≡ f 0 ( x ) ⋅ ( 1 − ln ⁡ f 0 ( x ) + h ( x ) ) ( m o d x n ) f(x)\equiv f_0(x)\cdot(1-\ln f_0(x)+h(x))\pmod{x^n} f(x)f0(x)(1lnf0(x)+h(x))(modxn)
用牛顿迭代的方法递归即可。

inline pol exp(pol g) {
    int n = g.size(), m = n >> 1;
    if(n == 1) return unipol(1);
    pol f0 = g; f0.resize(m);
    f0 = exp(f0); f0.resize(n);
    pol lnf0 = ln(f0);
    f0.resize(n<<1); lnf0.resize(n<<1); g.resize(n<<1);
    Add(g[0], 1);
    ntt(f0, 1); ntt(lnf0, 1); ntt(g, 1);
    for(int i = 0; i < n<<1; i++) g[i] = mul(f0[i], sub(g[i], lnf0[i]));
    ntt(g, 0);
    g.resize(n);
    return g;
}

多项式的幂

f g ( x ) ( x ) f^{g(x)}(x) fg(x)(x)

≡ e f ( x ) ln ⁡ g ( x ) ( m o d x n ) \equiv e^{f(x)\ln g(x)}\pmod{x^n} ef(x)lng(x)(modxn)
用多项式求对数和多项式exp即可。

Talk is cheap, show me the code!

[+] view code


FFT、NTT及FWT见多项式基础I。
多项式多点求值和多项式快速插值见多项式基础III。
另有任意模数NTT,无迹可循。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值