這一部分麻煩一點了,但是很重要,幾乎所有多項式都得用的,不過好在也不是很複雜的。
1. 多項式求逆
求一個多項式 的模 的逆元 時,假設先求出了模 的逆元 ,既:
那麼顯然存在:
兩邊同時平方:
再把 乘回去:
我們就可以倍增來處理它了,起點是
inline Polynomial Inverse(const Polynomial &a){
Polynomial ret,inv_a;
ret.resize(1);
ret[0]=Inv(a[0]);int ed=a.size();
for(int len=2;len<=ed;len<<=1){
int n=Prepare_Transformation(len+len);
inv_a=a;inv_a.resize(n);ret.resize(n);
for(int i=len;i<n;i++)inv_a[i]=0;
NTT(inv_a,1);NTT(ret,1);
for(int i=0;i<n;i++)ret[i]=1ll*(2ll-1ll*inv_a[i]*ret[i]%mod+mod)%mod*ret[i]%mod;
NTT(ret,-1);
//這裏把比較複雜的卷積過程拖下來了。
for(int i=len;i<n;i++)ret[i]=0;
//這裏不resize了,直接把多餘的清零。
}
ret.resize(ed);
//resize回來,防止以後長度爆炸。
return ret;
}
2. 多項式求導
按照公式來,公式挺簡單的,設多項式 的導數爲 。
那麼有:
既:
inline Polynomial Derivation(const Polynomial &a){
int size=a.size();Polynomial ret;ret.resize(size);
for(int i=1;i<size;i++)ret[i-1]=1ll*i*a[i]%mod;
ret[size-1]=0;
return ret;
}
3. 多項式求積
還是按照公式來,設多項式 的積分爲 。
那麼有:
既:
那就是乘逆元咯 (兄弟倆長得挺像
inline Polynomial Integral(const Polynomial &a){
int size=a.size();Polynomial ret;ret.resize(size);
for(int i=1;i<size;i++)ret[i]=1ll*Inv(i)*a[i-1]%mod;
ret[0]=0;
return ret;
}
4. 多項式複合逆
對於一個多項式,若是存在一個多項式,使得:
那麼就稱多項式是多項式的複合逆。
目前複合逆沒有的做法,但是可以用拉格朗日反演做到,既每一項每一項得求,求一項的時間是的,下面給出公式:
那麼求逆和卷積就好了,都挺好處理的,證明很複雜,感興趣可以看這裏。
有一個值得注意的地方就是求逆的時候,應該直接求的逆,而不是的逆,因爲既然多項式 存在複合逆,那麼常數項就應該是 ,這是不可能求逆的,先算出即可。
若是需要只求一項,則需要用到快速冪,下一篇我們會講到
inline Polynomial Composition_Inverse(const Polynomial &a){
int n=a.size();
Polynomial ret,Cinv=a,Pow;
Cinv.resize(n);ret.resize(n);Pow.resize(n);Pow[0]=1;
for(register int i=0;i<n-1;i++)Cinv[i]=Cinv[i+1];Cinv[n-1]=0;
Cinv=Inverse(Cinv);
for(register int i=1;i<n;++i){
Pow=Pow*Cinv;Pow.resize(n);
ret[i]=1ll*Pow[i-1]*Inv(i)%mod;
}
return ret;
}