markdown源码https://paste.ubuntu.com/p/wyNvxb4PPQ/
假设在modxn下,多项式A的逆元是F,在modx⌈n/2⌉下,多项式A的逆元是F0,根据多项式求逆的基本公式
F=2F0−F02Amodxn
首先定义,对于一个多项式F,F(k)为其在xk时的系数。
(当然,正确的写法是[xk]F,但是写起来不是很方便,因此修改了一下)
展开
F(x)=2F0(x)−j=0∑xF0(j)k=0∑x−jF0(k)A(x−j−k)
首先假设
R(x)=i=0∑xF0(i)A(x−i)
由逆元的定义可得在x<⌈2n⌉的情况下,R(x)=[x=0]。
-
对于x<⌈2n⌉的情况,可以得到
F(x)=2F0(x)−j=0∑xF0(j)R(x−j)
由于x<⌈2n⌉,因此R(x−j)只有在j=x时值为1,其他情况都为0,因此
F(x)=2F0(x)−F0(x)=F0(x)
-
对于x≥⌈2n⌉的情况,由于F0的次数为⌈2n⌉−1,因此F0(x)当x≥⌈2n⌉时值为0,
F(x)=−j=0∑xF0(j)R(x−j)
若x−j<⌈2n⌉,则R(x−j)=0,因此
F(x)=−j=0∑x−⌈n/2⌉F0(j)R(x−j)
定义
G=−F0[x⌈n/2⌉R]x⌈n/2⌉
其中,对于一个多项式F,定义[F]为F舍弃∀k<0,xk与其系数,例如[6x−3+2+5x]=2+5x。
展开得到
G(x)=−j=0∑n−1F0(j)R(x−j)[x−j≥⌈2n⌉]
即
G(x)=−j=0∑x−⌈n/2⌉F0(j)R(x−j)
容易发现
G(x)=F(x)
而G在求出R的基础上只需要求一个⌈2n⌉次多项式和一个n−⌈2n⌉次多项式的乘积,较为简便。
代码
inline int getinv(int *s,int len,int *res)
{
if(len==1)
{
res[0]=quickpow(s[0],mod-2);
return 0;
}
int k=(len+1)/2;
getinv(s,k,res);
for(int i=0; i<len; ++i)
{
tmp[i]=s[i];
}
multi(res,k,tmp,len,tmp,len);
multi(res,k,tmp+k,len-k,res+k,len-k);
for(int i=k; i<len; ++i)
{
if(res[i])
{
res[i]=mod-res[i];
}
}
return 0;
}
其中multi(int *a,int lena,int *b,int lenb,int *res,int k)
函数代表将多项式a
和多项式b
乘起来并modxk保存在res
数组中。