P5205,实际上过了,但是必须要开O2才能过,希望有大佬可以指出哪里可以优化。
代码:
#include<bits/stdc++.h>
using namespace std;
#define MAXN 600001
#define MAXM 1
#define ll long long
#define big __int128
#define type_ int
#define htype_ big
#define re register
#define G 3
inline void qr(type_ &res) {re type_ fh=1;res=0;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')fh=-1;for(;isdigit(ch);ch=getchar())res=(res<<3)+(res<<1)+(ch^'0');res=res*fh;}
inline type_ qp(type_ a,type_ b,type_ mod){
type_ ans=1;
while(b){if(b&1){ans=((ll)ans*a)%mod;}a=(ll)a*a%mod;b>>=1;}
return ans;
}
int rev[MAXN];
ostream &operator<<(ostream &os,big x){
int sta[100];int cnt=0;
do{sta[cnt++]=x%10;x/=10;}while(x);
while(cnt){putchar(sta[--cnt]+'0');}
return os;
}
void ms(type_ *a,type_ rep,int en){for(re int i=0;i<en;i++){a[i]=rep;}}
void exgcd(htype_ a,htype_ b,htype_ &x,htype_ &y){if(!b){x=1,y=0;return;}exgcd(b,a%b,x,y);re int t=x;x=y;y=t-(a/b)*y;}
inline int add(int x,int y,int mod){if(x+y>=mod){return x+y-mod;}return x+y;}
inline int sub(int x,int y,int mod){if(x-y<0){return x-y+mod;}return x-y;}
struct poly{
int len;
type_ p[3];
type_ a[MAXN][MAXM];
type_ value(int x,type_ mod,int chose=0){re type_ xn=1,ans=0;for(re int i=0;i<len;i++){ans=(ans+(ll)xn*a[i][chose]%mod)%mod;xn=(ll)xn*x%mod;}return ans;}
type_* operator[](int index){return a[index];}
void operator=(const poly &b){for(re int i=0;i<len;i++){for(re int j=0;j<MAXM;j++){a[i][j]=b.a[i][j];}}}
void print(int chose=0){for(re int i=0;i<len;i++){printf("%d ",a[i][chose]);}cout<<endl;}
int initrev(int n){int l=0,len=1;while(len<n){l++;len<<=1;}for(re int i=0;i<len;i++){rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));}return len;}
void G3NTT(int len,int type,int mod,int chose){
re int Gi=qp(G,mod-2,mod);
for(re int i=0;i<len;i++){if(i<rev[i]){swap(a[i][chose],a[rev[i]][chose]);}}
for(re int step=1;step<len;step<<=1){
re type_ Wn=qp(type==1?G:Gi,(mod-1)/(step<<1),mod);
for(re int st=0;st<len;st+=(step<<1)){re type_ W=1;
for(re int k=0;k<step;k++,W=((ll)W*Wn)%mod){
re int x=a[st+k][chose],y=(ll)W*a[st+k+step][chose]%mod;
a[st+k][chose]=add(x,y,mod);a[st+k+step][chose]=sub(x,y,mod);
}
}
}
if(type==-1){type_ inv=qp(len,mod-2,mod);for(re int i=0;i<len;i++){a[i][chose]=(ll)a[i][chose]*inv%mod;}}
}
void clear(int en=MAXN){len=0;for(re int i=0;i<MAXM;i++){ms(a[i],0,en);}}
poly(){p[0]=998244353,p[1]=1004535809,p[2]=469762049;}
poly(int n){p[0]=998244353,p[1]=1004535809,p[2]=469762049;len=n;for(re int i=0;i<MAXM;i++){ms(a[i],0,n);}}
};
ll sqrt1(ll a,ll p){
if(a==1){return 1;}
return 0;
}
void multiply(poly &a,poly &b,type_ mod){
int n=a.len+b.len-1;int bn=b.len;int len=a.initrev(n);
for(re int i=n;i<len;i++){a[i][0]=b[i][0]=a[i][1]=b[i][1]=a[i][2]=b[i][2]=0;}a.len=b.len=len;
for(re int j=0;j<MAXM;j++){
a.G3NTT(len,1,a.p[j],j);b.G3NTT(len,1,b.p[j],j);
for(re int i=0;i<len;i++){a[i][j]=(ll)a[i][j]*b[i][j]%a.p[j];}
a.G3NTT(len,-1,a.p[j],j);
}
for(re int i=0;i<len;i++){
htype_ n=1,ans=0;
for(re int j=0;j<MAXM;j++){n=n*a.p[j];}
for(re int j=0;j<MAXM;j++){
htype_ m=n/a.p[j],b,y;
exgcd(m,a.p[j],b,y);
b=(b+a.p[j])%a.p[j];
ans=(ans+(ll)a[i][j]*m%n*b%n)%n;
}
ans=(ans+n)%n;a[i][0]=ans%mod;
}
for(re int i=n;i<len;i++){a[i][0]=a[i][1]=a[i][2]=0;}
for(re int i=bn;i<len;i++){b[i][0]=b[i][1]=b[i][2]=0;}
a.len=n;b.len=bn;
}
poly A,B,A_1,C_1;
inline void inv(poly a,int n,poly &ans,type_ mod){
ans[0][0]=qp(a[0][0],mod-2,mod);ans.len=n;
for(re int N=1;N<(n<<1);N<<=1){
int Nn=N+N;int len=a.initrev(Nn);
for(re int i=0;i<N;i++){A[i][0]=a[i][0];B[i][0]=ans[i][0];}
for(re int i=N;i<n*2;i++){A[i][0]=B[i][0]=0;}
A.G3NTT(len,1,mod,0);B.G3NTT(len,1,mod,0);
for(re int i=0;i<len;i++){ans[i][0]=(ll)B[i][0]*(sub(2ll,(ll)A[i][0]*B[i][0]%mod,mod))%mod;}
ans.G3NTT(len,-1,mod,0);
for(re int i=N;i<len;i++){ans[i][0]=0;}
}
int len=a.initrev(n*2);
for(int i=n;i<len;i++){ans[i][0]=0;}
}
inline void sqrt(poly a,int n,poly &ans,type_ mod){
ans[0][0]=sqrt1(a[0][0],mod);ans.len=n;
for(re int N=1;N<(n<<1);N<<=1){
int Nn=N+N;int len=a.initrev(Nn);
for(re int i=0;i<N;i++){A_1[i][0]=a[i][0];C_1[i][0]=0;}
for(re int i=N;i<len;i++){A_1[i][0]=C_1[i][0]=0;}
inv(ans,N,C_1,mod);
A_1.G3NTT(len,1,mod,0);ans.G3NTT(len,1,mod,0);C_1.G3NTT(len,1,mod,0);
int inv2=qp(2,mod-2,mod);
for(re int i=0;i<len;i++){ans[i][0]=(ll)inv2*(add((ll)ans[i][0],(ll)C_1[i][0]*A_1[i][0]%mod,mod))%mod;}
ans.G3NTT(len,-1,mod,0);for(re int i=n;i<len;i++){ans[i][0]=0;}
}
}
poly a,b;
int main(){
int n;
cin>>n;
a.len=n;
for(re int i=0;i<n;i++){qr(a[i][0]);}
sqrt(a,n,b,998244353);
b.print();
}