学习了一下大佬的->
已知多项式$A(x)$,若存在$A(x)B(x)\equiv 1\pmod{x^n}$
则称$B(x)$为$A(x)$在模$x^n$下的逆元,记做$A^{-1}(x)$
具体的来说的话,就是两个多项式$A,B$相乘模$x^n$之后,所有次数大于等于$n$的项都没了,那么只有在剩下的项相乘之后未知数项全被消掉只留下一个常数项$1$时,$B$才是$A$的逆元
然后为什么要有模$x^n$的限制呢?因为没有这个限制的话,$B$可能有无穷多项
然后我们考虑如何计算$B(x)$
当$n=1$的时候,$A(x)\equiv c\pmod{x}$,其中$c$为常数项,那么$A^{-1}(x)$就是$c^{-1}$
当$n>1$时$$B(x)A(x)\equiv 1\pmod{x^n}$$
设$B'(x)$是模$x^{\left\lceil\frac{n}{2}\right\rceil}$时的逆元,即$$B'(x)A(x)\equiv 1\pmod{x^{\left\lceil\frac{n}{2}\right\rceil}}$$
首先,可以肯定$$B(x)A(x)\equiv 1\pmod{x^{\left\lceil\frac{n}{2}\right\rceil}}$$
那么上下两个式子相减可得$$B(x)-B'(x)\equiv 0\pmod{
{x^{\left\lceil\frac{n}{2}\right\rceil}}}$$然后两边平方$$B^2(x)-2B'(x)B(x)+B'^2(x)\equiv 0\pmod{
{x^n}}$$为什么上面模数变成$x^n$呢?我们考虑如果一个多项式在$\pmod{x^n}$的情况下为$0$,那么说明$0$到$n-1$项的系数也为$0$,它平方之后$0$到$2n-1$项系数$a_i$为$\sum_{j=0}^ia_ja_{i-j}$,那么$j$和$i-j$中必有一个小于$n$,也就是说$a_j$和$a_{i-j}$里必有一个为$0$,那么$a_i$也是$0$,所以平方之后在$\mod{2n}$也为$0$
然后在上式两边同乘$A(x)$并移项可得$$B(x)\equiv2B'(x)-A(x)B'^2(x)\pmod{x^n}$$
那么发现这个东西可以递归计算,时间复杂度为$O(nlogn)$
1 //minamoto 2 #include3 #include 4 #include 5 #define swap(x,y) (x^=y,y^=x,x^=y) 6 #define mul(x,y) (1ll*x*y%P) 7 #define add(x,y) (x+y>=P?x+y-P:x+y) 8 #define dec(x,y) (x-y<0?x-y+P:x-y) 9 using namespace std;10 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)11 char buf[1<<21],*p1=buf,*p2=buf;12 inline int read(){13 #define num ch-'0'14 char ch;bool flag=0;int res;15 while(!isdigit(ch=getc()))16 (ch=='-')&&(flag=true);17 for(res=num;isdigit(ch=getc());res=res*10+num);18 (flag)&&(res=-res);19 #undef num20 return res;21 }22 char sr[1<<21],z[20];int C=-1,Z;23 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}24 inline void print(int x){25 if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;26 while(z[++Z]=x%10+48,x/=10);27 while(sr[++C]=z[Z],--Z);sr[++C]=' ';28 }29 const int N=(1<<21)+5,P=998244353,G=3,Gi=332748118;30 inline int ksm(int a,int b){31 int res=1;32 while(b){33 if(b&1) res=mul(res,a);34 a=mul(a,a),b>>=1;35 }36 return res;37 }38 int n,r[N],X[N],Y[N],A[N],B[N],O[N];39 void NTT(int *A,int type,int len){40 int limit=1,l=0;41 while(limit >1]>>1)|((i&1)<<(l-1));44 for(int i=0;i >1);66 for(int i=0;i