Description
Given a \ (n-1 \) Polynomial \ (A (X) \) , in seeking a \ (\ bmod x ^ n \ ) polynomial in the sense of \ (B (X) \) , such that \ (B ^ 2 (x) \ equiv A (x) (\ bmod x ^ n) \)
Polynomial coefficients \ (\ bmod \ 998244353 \) calculates the sense of.
\(n \leq 10^5,a_i \in [0,998244352] \cap \mathbb{Z}\)
Solution
In fact, the derivation and similar inverse polynomial
Consider doubling
Suppose we have obtained a polynomial \ (G (x) \) such that \ (G ^ 2 (x) \ equiv A (x) \ (\ bmod \ x ^ {\ lceil \ frac {n} {2} \ } rceil) \) , and \ (B (x) \) , there have been \ (B ^ 2 (x) \ equiv A (x) \ (\ bmod \ x ^ {\ lceil \ frac {n} {2} \ rceil}) \) , then
\ [B ^ 2 (x) -G ^ 2 (x) \ equiv 0 (\ bmod x ^ {\ lceil \ frac {n} {2} \ rceil}) \ tag {1 } \]
squares difference equation expand
\ [(B (x) -G (x)) (B (x) + G (x)) \ equiv 0 (\ bmod x ^ {\ lceil \ frac {n} {2} \ rceil}) \ tag {2
} \] where we need to say what, what difference would it really take issue
Assuming that the subject requirements of the final answer is \ (F (x) \)
Because operation performed in modulo large prime significance, so either there \ (B (X) \ equiv G (X) (\ BMOD X ^ {\ lceil \ FRAC {n-} {2} \ rceil}) \) , either have \ (B (X) + G (X) \ equiv 0 (\ BMOD X ^ {\ lceil \ FRAC {n-} {2} \ rceil}) \) , as to why only need to look \ (0 \) order term coefficient on it
If we in the multiplication of all select \ (B (x) \ equiv G (x) (\ bmod x ^ {\ lceil \ frac {n} {2} \ rceil}) \) or a selected even number of times \ ( B (X) + G (X) \ equiv 0 (\ BMOD X ^ {\ lceil \ FRAC {n-} {2} \ rceil}) \) , then the resulting answer is \ (F. (X) \) , On the contrary, if we choose the odd \ (B (X) + G (X) \ equiv 0 (\ BMOD X ^ {\ lceil \ FRAC {n-} {2} \ rceil}) \) , then the resulting answer is \ (- F. (X) \) , the reason in the following derivation is easy to see. Therefore, \ (\ sqrt {A (x )} \) there are two solutions for \ (\ pm F (x) \)
We chose the former, i.e.
\ [B (x) \ equiv
G (x) \ (\ bmod x ^ {\ lceil \ frac {n} {2} \ rceil}) \ tag {3} \] After transposing square Expand to give
\ [B ^ 2 (x)
-2B (x) G (x) + G ^ 2 (x) \ equiv 0 (\ bmod x ^ n) \ tag {4} \] i.e.
\ [A (x) - 2B (x) G (x)
+ G ^ 2 (x) \ equiv 0 (\ bmod x ^ n) \ tag {5} \] transposing obtain
\ [2B (x) G ( x) \ equiv A (x ) + G ^ 2 (x)
(\ bmod x ^ n) \ tag {6} \] and dividing the past, have
\ [B (x) \ equiv \ frac {A (x) + G ^ 2 (x)} {2G (x)} (\
bmod x ^ n) \ tag {7} \] polynomial inverse + \ (\ text NTT} {\) to
#include<cstdio>
#include<iostream>
using namespace std;
const int N=1e5+10;
const int mod=998244353;
const int g=3;
const int invg=332748118;
int n,a[N<<2],b[N<<2],c[N<<2],d[N<<2],f[N<<2],h[N<<2],k;
inline void Add(int &x,int y){x+=y;x-=x>=mod? mod:0;}
inline int MOD(int x){x-=x>=mod? mod:0;return x;}
inline int fas(int x,int p){int res=1;while(p){if(p&1)res=1ll*res*x%mod;p>>=1;x=1ll*x*x%mod;}return res;}
inline void NTT(int *a,int f){
for(register int i=0,j=0;i<k;i++){
if(i>j)swap(a[i],a[j]);
for(register int l=k>>1;(j^=l)<l;l>>=1);}
for(register int i=1;i<k;i<<=1){
int w=fas(~f? g:invg,(mod-1)/(i<<1));
for(register int j=0;j<k;j+=(i<<1)){
int e=1;
for(register int p=0;p<i;p++,e=1ll*e*w%mod){
int x=a[j+p],y=1ll*a[j+p+i]*e%mod;
a[j+p]=MOD(x+y);a[j+p+i]=MOD(x-y+mod);
}
}
}
}
inline void PINV(int *a,int *b,int deg){
if(deg==1){b[0]=fas(a[0],mod-2);return;}
int M=(deg+1)>>1;PINV(a,b,M);
k=1;while(k<=deg+deg-2)k<<=1;int INV=fas(k,mod-2);
for(register int i=0;i<deg;i++)h[i]=a[i];
for(register int i=deg;i<k;i++)h[i]=0;
NTT(h,1);NTT(b,1);
for(register int i=0;i<k;i++)
b[i]=(2ll-1ll*h[i]*b[i]%mod+mod)*b[i]%mod;
NTT(b,-1);
for(register int i=0;i<deg;i++)b[i]=1ll*b[i]*INV%mod;
for(register int i=deg;i<k;i++)b[i]=0;
}
inline void Sqrt(int *a,int *b,int deg){
if(deg==1){b[0]=1;return;}
int M=(deg+1)>>1;Sqrt(a,b,M);
k=1;while(k<=deg+deg-2)k<<=1;int INV=fas(k,mod-2);
for(register int i=0;i<deg;i++)c[i]=b[i];
for(register int i=deg;i<k;i++)c[i]=0;
NTT(c,1);
for(register int i=0;i<k;i++)c[i]=1ll*c[i]*c[i]%mod;
NTT(c,-1);
for(register int i=0;i<deg;i++)c[i]=1ll*c[i]*INV%mod;
for(register int i=deg;i<k;i++)c[i]=0;
for(register int i=0;i<deg;i++)Add(c[i],a[i]);
for(register int i=0;i<deg;i++)d[i]=MOD(b[i]+b[i]);
for(register int i=deg;i<k;i++)d[i]=0;
for(register int i=0;i<k;i++)f[i]=0;
PINV(d,f,deg);
k=1;while(k<=deg+deg-2)k<<=1;
NTT(f,1);NTT(c,1);
for(register int i=0;i<k;i++)b[i]=1ll*f[i]*c[i]%mod;
NTT(b,-1);
for(register int i=0;i<deg;i++)b[i]=1ll*b[i]*INV%mod;
}
int main(){
scanf("%d",&n);n--;
for(register int i=0;i<=n;i++)scanf("%d",&a[i]);
Sqrt(a,b,n+1);
for(register int i=0;i<=n;i++)printf("%d%c",b[i],i==n? '\n':' ');
return 0;
}