Luogu P5205 [template] open polynomial root

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;
}

Guess you like

Origin www.cnblogs.com/ForwardFuture/p/11511401.html