【learning】多項式相關(求逆、開根、除法、取模)

(首先要%miskcoo,這位dalao寫的博客實在是太強啦qwq大部分多項式相關的知識都是從這位dalao博客裏面學的,做爲一隻蒟蒻仍是瘋狂膜拜後本身理下思路吧qwq)函數


多項式求逆(元)

  • 定義

  對於一個多項式\(A(x)\),若是存在一個多項式\(B(x)\),知足\(B(x)\)的次數小於等於\(A(x)\)\(A(x)B(x)\equiv 1(mod\ x^n)\),那麼咱們稱\(B(x)\)\(A(x)\)在模\(x^n\)意義下的逆元,簡單記做\(A^{-1}(x)\)ui

  • 求解

  從最簡單的狀況開始考慮,當\(n=1\)的時候\(A(x)\equiv\ c\ (mod\ x)\)\(c\)\(A(x)\)的常數項,此時\(A^{-1}(x)\)\(c\)的逆元spa

  在這個基礎上咱們繼續考慮通常狀況code

  對於\(n>1\)的狀況,不妨設\(B(x)=A^{-1}(x)\),那麼咱們能夠根據定義列出下面的式子:
\[ A(x)B(x)\equiv 1(mod\ x^n) \]
  這裏的話考慮用倍增的方式求解(算倍增吧),這裏假設咱們已經知道了\(A(x)\)\(mod\ x^{\lceil \frac{n}{2} \rceil}\)下的逆元\(G(x)\),那麼有:
\[ A(x)G(x)\equiv 1(mod\ x^{\lceil \frac{n}{2} \rceil}) \]
  咱們把\(A(x)\)\(B(x)\)的式子寫成\(mod\ x^{\lceil \frac{n}{2} \rceil}\)下的:blog

  (能夠這麼寫是由於\(mod\ x^n\)至關於將乘積中\(x\)次數大於等於\(n\)的忽略掉了,而\(mod\ x^{\lceil \frac{n}{2} \rceil}\)則至關於忽略了更多的項,既然前者知足,那麼後者確定也知足)遞歸

\[ A(x)B(x)\equiv 1 (mod\ x^{\lceil \frac{n}{2} \rceil}) \]get

  把這兩條式子相減,就能夠搞事情了:
\[ \begin{aligned} A(x)[B(x)-G(x)]&\equiv 0\ (mod\ x^{\lceil \frac{n}{2} \rceil})\\ B(x)-G(x)&\equiv 0\ (mod\ x^{\lceil \frac{n}{2} \rceil})\\ \end{aligned} \]
  而後咱們兩邊平方一下:
\[ B^2(x)-2B(x)G(x)+G^2(x)\equiv 0\ (mod\ x^{\lceil \frac{n}{2} \rceil}) \]
  而後這裏有個很神奇的事情,\(B(x)-G(x)\)\(mod\ x^{\lceil \frac{n}{2} \rceil}\)下爲0,說明這個式子最後的結果的\(0\)\(\lceil \frac{n}{2} \rceil -1\)次項係數都爲\(0\),平方了以後,對於結果的\(i\)次項係數,(\(0<=i<=2*\lceil \frac{n}{2} \rceil -1\) ),其係數\(a_i = \sum\limits_{j=0}^{i}a_j a_{i-j}\),而\(a_j\)\(a_{i-j}\)中一定有一項爲\(0\)(由於\(j\)\(i-j\)中一定有一個值小於\(\lceil \frac{n}{2} \rceil\)),因此咱們能夠獲得一個結論,這個式子在平方了以後在\(mod \ x^n\)下也是\(0\)博客

  那麼咱們就能夠寫成:
\[ \begin{aligned} B^2(x)-2B(x)G(x)+G^2(x)&\equiv 0\ (mod\ x^n)\\ A(x)B(x)*B(x)-2*A(x)B(x)*G(x)+A(x)G^2(x)&\equiv 0\ (mod\ x^n)\\ \end{aligned} \]
  兩邊同時乘上\(A(x)\),由逆元的定義咱們能夠將上面的式子化簡成下面這樣:
\[ B(x)-2G(x)+A(x)G^2(x)\equiv 0\ (mod\ x^n) \]
  最後獲得:
\[ B(x)\equiv 2G(x)-A(x)G^2(x)\ (mod\ x^n) \]
  也就是說,若是咱們知道\(G(x)\),咱們就能夠推出\(B(x)\)it

  具體的實現能夠用遞歸的方式實現,中間的多項式乘法能夠用fft加速一下,那麼最終的時間複雜度就是
\[ T(n)=T(\frac{n}{2})+O(n \ log\ n)=O(n\ log \ n) \]
  然而爲啥這樣搞完了仍是一個log呢?由於每次遞歸下去多項式的最高次數都會減半,稍微算一下就會發現最後總的時間複雜度合起來仍是一個log而不是兩個io

  注意,後面這一堆推式子的過程是創建在\(n=1\)的時候有解的前提下的,因此咱們還能夠獲得一個結論:一個多項式在\(mod\ x^n\)下是否有逆元取決於其常數項在\(mod \ x^n\)下是否有逆元

  • 實現

  首先先實現一個namespace NTT,而後除了基礎的函數外主要供外部調用的過程是這個:

void Ntt_getinv(vct &a,vct &b,int n,int m){
    prework(a,b,n,2*m);//這裏注意由於後面是A*B*B,因此m要*2
    ntt(A,1);
    ntt(B,1);
    for (int i=0;i<len;++i) 
        B[i]=(2LL-1LL*A[i]*B[i]%MOD+MOD)*1LL*B[i]%MOD;
    ntt(B,-1);
}

  而後求逆的過程大概是這樣(這裏用vector來寫了):

vct Inv(vct a){
    int N=a.size();
    if (N==1){
        a[0]=ksm(a[0],MOD-2);
        return a;
    }
    vct b=a; b.resize((N+1)>>1);
    b=Inv(b); b.resize(N);
    NTT::Ntt_getinv(a,b,N,N);
    b.resize(NTT::len);
    for (int i=0;i<NTT::len;++i) b[i]=NTT::B[i];
    b.resize(N);
    return b;
}

  求逆大概就是這樣吧ovo

  

多項式開根

  • 定義

  對於一個多項式\(A(x)\),若是存在一個多項式\(B(x)\),知足\(B^2(x)\equiv\ A(x) (mod\ x^n)\),則稱\(B(x)\)\(A(x)\)\(mod\ x^n\)下的平方根

  • 求解

  一樣是考慮最簡單的狀況,當\(n=0\)的時候,\(B(x)\)的常數項就是\(1\)

  而後考慮通常狀況,一樣的思路,考慮用倍增的方式來求

  假設咱們已經知道了\(A(x)\)\(mod\ x^{n}\)下的平方根\(G(x)\),如今要求在\(mod\ x^{2n}\)下的平方根\(B(x)\),根據定義咱們能夠列出式子:
\[ \begin{aligned} B^2(x)&\equiv A(x)(mod\ x^{2n})\\ G^2(x)&\equiv A(x)(mod\ x^n) \end{aligned} \]
  咱們對這個式子進行一些處理:
\[ \begin{aligned} G^2(x)&\equiv A(x)(mod\ x^n)\\ G^2(x)-A(x)&\equiv 0(mod\ x^n)\\ \end{aligned} \]
  那麼能夠獲得(由於右邊是\(0\)因此能夠這麼搞):
\[ \begin{aligned} (G^2(x)-A(x))^2&\equiv 0 (mod\ x^{2n})\\ G^4(x)-2G^2(x)A(x)+A^2(x)&\equiv 0(mod\ x^{2n})\\ \end{aligned} \]
  而後兩邊加上\(4G^2(x)A(x)\)
\[ \begin{aligned} G^4(x)+2G^2(x)A(x)+A^2(x)&\equiv 4G^2(x)A(x)(mod\ x^{2n})\\ (G^2(x)+A(x))^2&\equiv 4G^2(x)A(x)(mod\ x^{2n})\\ (G^2(x)+A(x))^2&\equiv (2G(x))^2A(x)(mod\ x^{2n})\\ \end{aligned} \]
  咱們將\((2G^2(x))^2\)移到左邊去,將左邊寫成一個平方的形式,獲得:
\[ (\frac{G^2(x)+A(x)}{2G(x)})^2\equiv A(x)(mod\ x^{2n}) \]
  等式左邊的東西就是咱們要求的\(B(x)\)

  因此若是說咱們知道了\(G(x)\),咱們也就能夠得出\(B(x)\)啦,分母能夠用多項式求逆搞一下,其餘的多項式乘法fft搞一下,問題不大

  總的複雜度是:
\[ T(n)=T(\frac{n}{2})+求逆複雜度+O(n\ log \ n)=O(n\ log\ n) \]

  

  • 實現

  namespace NTT中主要須要調用的過程長這個樣子

void Ntt_getsqrt(vct &a,vct &invb,int n,int m){
    prework(a,invb,n,m);
    ntt(A,1);
    ntt(B,1);
    for (int i=0;i<len;++i) 
        B[i]=1LL*B[i]*inv2%MOD*A[i]%MOD;
    ntt(B,-1);
}

  開根的話大概長這個樣子

vct Sqrt(vct a){
    int N=a.size(),M,M1;
    if (N==1){
        a[0]=1;
        return a;
    }
    vct b=a,invb;
    b.resize((N+1)>>1);
    b=Sqrt(b);
    invb=b; invb.resize(N);//resize!!!
    invb=Inv(invb);
    NTT::Ntt_getsqrt(a,invb,N,N);
    b.resize(NTT::len);
    for (int i=0;i<NTT::len;++i) b[i]=(1LL*b[i]*inv2%MOD+NTT::B[i])%MOD;
    b.resize(N);
    return b;
}

  
  
  

多項式除法

  • 問題

  給出一個\(n\)次多項式\(A(x)\),以及一個\((m(m<=n)\)次多項式\(B(x)\)

  要求出\(D(x)\)知足\(A(x)=D(x)B(x)+R(x)\),且\(D(x)\)的次數\(<=n-m\)\(R(x)\)的次數\(<m\)

  簡單來講就是類比整數的除法,\(D(x)\)就是商,\(R(x)\)就是餘數,咱們如今考慮求商

  • 求解

  爲了方便接下來的表述,先定義一些操做,咱們記:
\[ rev(A(x))=x^nA(\frac{1}{n}) \]
  也就是係數反轉,舉個簡單的例子:
\[ \begin{aligned} A(x)&=4x^4+3x^3+2x^2+1\\ rev(A(x))&=x^4+2x^3+3x^2+4 \end{aligned} \]
  那麼如今咱們把上面那條式子搬下來:
\[ A(x)=D(x)B(x)+R(x) \]
  (接下來的步驟均將\(D(x)\)當作\(n-m\)次多項式,\(R(x)\)當作\(m-1\)次多項式,對於那些不存在的高次項咱們就把係數當作\(0\)就行了)

  後面的餘數看起來十分不友善,因此咱們要想個辦法把它去掉,因而咱們能夠進行如下的操做:

  咱們將上面式子中的全部\(x\)換成\(\frac{1}{x}\),而後等式兩邊同時乘上\(x^n\),獲得:
\[ \begin{aligned} x^nA(\frac{1}{x})&=x^{n-m}D(\frac{1}{x})x^mB(\frac{1}{x})+x^{n-m+1}x^{m-1}R(\frac{1}{x})\\ rev(A(x))&=rev(D(x))rev(B(x))+x^{n-m+1}rev(R(x))\\ \end{aligned} \]
  如今再來看一下各個項的最高次項,首先是咱們要求的元素\(D(x)\),因爲這個多項式原來是\(n-m\)次,因此在係數反轉以後確定不會超過\(n-m\)次,而咱們要「消掉」的\(R(x)\)原來是\(m-1\)次多項式,因此\(x^{n-m+1}R(x)\)最低次項應該是大於\(n-m\)

  那麼考慮將上面的式子放到\(mod\ x^{n-m+1}\)下,\(x^{n-m+1}R(x)\)的影響就能夠十分愉快滴被消掉啦,同時咱們也不會影響到\(D(x)\)的求解,由於\(D(x)\)\(n-m\)次的(瘋狂%miskcoo太強了qwq)

  因而咱們就獲得了這樣一個式子:
\[ rev(A(x))\equiv\ rev(D(x))rev(B(x))\ (mod\ x^{n-m+1}) \]
  那因此,咱們只要求一個\(rev(B(x))\)\(mod x^{n-m+1}\)意義下的逆元而後跟\(rev(A(x))\)乘一下,獲得\(rev(D(x))\),而後再把係數反轉回來就獲得\(D(x)\)

  • 實現

  除法大概是長這個樣子

vct operator / (vct a,vct b){
    int N=a.size()-1,M=b.size()-1;
    if (N<M){
        d.resize(1);d[0]=0;
        return d;
    }
    reverse(a.begin(),a.end());
    reverse(b.begin(),b.end());
    b.resize(N-M+1);
    d=Inv_p(b)*a;
    d.resize(N-M+1);
    reverse(d.begin(),d.end());
    return d;
}

多項式取模

  • 問題

   這個。。其實就是求上面那個\(R(x)\)

  • 求解

  有了多項式除法(也就是求商)以後,求餘數就變得比較簡單了

  類比整數的取模,咱們能夠獲得這樣的一個式子:
\[ R(x)=A(x)-D(x)B(x) \]
  那就除法求出\(D(x)\)以後直接減一下就行了,\(D(x)B(x)\)這個多項式乘法也是直接用\(fft\)求就行了

  • 實現

  僞裝很是短的樣子 (然而前面的東西都是要寫的qwq醒醒)

void mod(vct &a,vct b){
    int N=a.size()-1,M=b.size()-1;
    if (N<M) return;
    t=a/b;
    a=a-(t*b);
    a.resize(M);
}

 
  大概。。就先寫這麼多吧ovo

相關文章
相關標籤/搜索