1. 程式人生 > 實用技巧 >多項式全家桶系列

多項式全家桶系列

前置知識

FFT,NTT等數論基礎知識

多項式求逆

題意

給定一個多項式$F(x)$,求一個多項式$G(x)$,使得$F(x)G(x) \equiv 1\qquad\mod x^n$

$n \le 10^5$

方法

在處理多項式問題中,二分法是一個很常見的方法

我們假設求出了在模$\lfloor\frac n2\rfloor$上$F(x)$的逆$H(x)$

那麼我們有

$$F(x)H(x)\equiv 1\qquad\mod x^{\lfloor\frac n2\rfloor}$$

由題,顯然可得

$$F(x)G(x)\equiv 1\qquad\mod x^{\lfloor\frac n2\rfloor}$$

兩式相減

$$G(x)-H(x)\equiv 0\qquad\mod x^{\lfloor\frac n2\rfloor}$$

兩邊平方

$$G^2(x)-2G(x)H(x)+H^2(x)\equiv 0\qquad\mod x^n$$

兩邊同乘$F(x)$

$$F(x)G^2(x)-2F(x)G(x)H(x)+F(x)H^2(x)\equiv 0\qquad\mod x^n$$

由$G(x)F(x)\equiv 1\qquad\mod x^n$得

$$G(x)-2H(x)+F(x)H^2(x)\equiv 0\qquad\mod x^n$$

$$G(x)\equiv 2H(x)-F(x)H^2(x)\qquad\mod x^n$$

邊界條件:只剩常數項時所求逆即為該數的逆元。

getinv

上述程式碼中$a$為原陣列,$b$為所求逆,$c$為輔助陣列

多項式對數函式

題意

給定多項式$F(x)$,求一個多項式$G(x)$,使得$G(x)\equiv\ln F(x)\qquad\mod x^n$

$n\le 10^5$

方法

設函式$f(x)=\ln(x)$

則我們要求的式子變為

$$G(x)\equiv f(F(x))\qquad\mod x^n$$

兩邊求導,根據複合函式求導$f(g(x))'=f'(g(x))g'(x)$,得

$$G'(x)\equiv\frac{F'(x)}{F(x)}\qquad\mod x^n$$

對$F(x)$求導得$F'(x)$,求逆得$\frac{1}{F(x)}$,兩式相乘得$G'(x)$,再積分則可得$G(x)$

多項式求導

已知$$F(x) = \sum_{i = 0}^{n} a_ix^i$$

則$$F'(x) = \sum_{i=0}^{n-1} a_{i+1}*(i+1)x^i$$

假設$F(x) = 4x^3+5x^2+2x+4$,那麼$F'(x)=12x^2+10x+2$

多項式積分

求導的逆運算。

對於$a[i]$,直接乘上$i$的逆元即可。

View Code

多項式exp

題意

給定多項式$F(x)$,求一個多項式$G(x)$,使得$G(x)\equiv e^{F(x)}\qquad\mod x^n$

$n\le 10^5$

方法

過程需要使用牛頓迭代和泰勒展開,因此只給結論

假設我們求得$H(x)$滿足

$$H(x)\equiv e^{F(x)}\qquad\mod x^{\lfloor\frac n2\rfloor}$$

$$G(x)\equiv H(x)(1-\ln(H(x))+F(x))\qquad\mod x^n$$

View Code

多項式快速冪

題意

給定多項式$F(x)$與整數$m$,求多項式$G(x)$,使得$G(x)\equiv F^m(x)\qquad\mod x^n$

$n\le 10^5,m\le 10^{10^5}$

方法

$$G(x)\equiv F^m(x)\qquad\mod x^n$$

兩邊同時取對數,得

$$\ln G(x)\equiv m\ln F(x)\qquad\mod x^n$$

求出$\ln G(x)$後再進行exp即可。

View Code

但是ln與exp預設常數項為$1$,當多項式常數項不為1時需要特殊處理

當常數項為$0$時,需要將多項式平移至常數項不為$0$

若常數項不為$1$,則需要將所有係數同時除以常數項

多項式開根

題意

給定多項式$F(x)$,求多項式$G(x)$,使得$G^2(x)\equiv F(x)\qquad\mod x^n$

$n\le 10^5$

方法

假設$H(x)$滿足$$H^2(x)\equiv F(x)\qquad\mod x^{\lfloor\frac n2\rfloor}$$

顯然有$$G^2(x)\equiv F(x)\qquad\mod x^{\lfloor\frac n2\rfloor}$$

那麼有$$G(x)\equiv H(x)\qquad\mod x^{\lfloor\frac n2\rfloor}$$

把$H(x)$扔過來,兩邊平方,得$$G^2(x)-2H(x)G(x)+H^2(x)\equiv 0\qquad\mod x^n$$

$$F(x)-2H(x)G(x)+H^2(x)\equiv 0\qquad\mod x^n$$

$$G(x)\equiv \frac{H^2(x)+F(x)}{2H(x)}\qquad\mod x^n$$

邊界條件:假設給定多項式的常數項為$x$,我們要找到一個$y$,使$y^2\equiv x \mod 998244353$

二次剩餘定理

若$y^2\equiv x\qquad\mod p$,則稱$y$是$x$在模$p$意義下的二次剩餘

定義勒讓德符號

$$ (\frac np)=\left\{ \begin{aligned} x & = 1 \qquad n在模p意義下是二次剩餘\\ y & = 0 \qquad p | n \\ z & = -1 \qquad n在模p意義下是二次非剩餘 \end{aligned} \right. $$

那麼我們有尤拉判別準則

$$(\frac np)\equiv n^{\frac {p-1}2}\qquad\mod p$$

Cipolla演算法流程

第一步,判斷方程是否有解

第二步,隨機找一個$a$,使得數$w=(a^2-x)%p$,且$w$在模$p$意義下為非二次剩餘

第三部,找到一個解$y\equiv (a+\sqrt(w)^{\frac{p +1}2})\qquad\mod p$,因為$\sqrt w$不存在,所以將$\sqrt w$當作虛數即可

struct cp {
    int x, y;
    cp(int xx = 0, int yy = 0) {x = xx, y = yy;}
    cp operator * (cp A) {return (cp){(A.x * x % Mod + y * A.y % Mod * w % Mod) % Mod, (A.x * y % Mod + A.y * x % Mod) % Mod};}
};
int Qpow(cp a, int b) {
    cp res(1, 0);
    while(b) {
        if(b & 1)  res = res * a;
        a = a * a;
        b >>= 1;
    }
    return res.x;
}
int Calc(int x) {
    srand(time(0));
    if(qpow(x, (Mod - 1) >> 1) == Mod - 1)  return -1;
    while(1) {
        int a = rand() * rand() % Mod;
        w = (a * a % Mod - x + Mod) % Mod;
        if(qpow(w, (Mod - 1) >> 1) == Mod - 1)
            return Qpow(cp(a, 1), (Mod + 1) >> 1);
    }
}
void Sqrt(int len, int *a, int *b) {
    if(len == 1) {
        b[0] = Calc(a[0]);
        b[0] = min(b[0], Mod - b[0]);
        return;
    }
    Sqrt((len + 1) >> 1, a, b);
    memset(d, 0, sizeof(d));
    getinv(len, b, d);
    getl(len << 1);
    for(int i = 0; i < len; i++)  c[i] = a[i];
    for(int i = len; i < lim; i++)  c[i] = 0;
    ntt(b, 1); ntt(d, 1); ntt(c, 1);
    for(int i = 0; i < lim; i++)
        b[i] = (b[i] + c[i] * d[i] % Mod) % Mod * qpow(2, Mod - 2) % Mod;
    ntt(b, -1);
    for(int i = len; i < lim; i++)  b[i] = 0;
}
View Code