如果把 N 开到 219 就可以通过,可按理来说只需要两倍空间啊?
中间具体思路大概是用牛顿迭代推出的式子:
f(x)=2f0(x)−f0(x)2h(x)
注意到前面一半的项数是不变的,将后面一坨式子的后一半项数提出来再拼上 f0。
但是它需要四倍空间,求帮忙看看为啥。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll N=(1<<18)+13,H=998244353,g=3,ig=(H+1)/3;
int U[N];
ull W[N];
ll Ksm(ll x,ll y=H-2)
{
ll s=1;
for(ll i=1;i<=y;i<<=1,x=x*x%H)if(i&y)s=s*x%H;
return s;
}
void Init(int L){for(int i=0;i<L;i++)U[i]=U[i/2]/2|(i&1?L/2:0);}
void Clr(ull *A,int l,int r){memset(A+l,0,(r-l+1)<<3);}
void Cpy(ull *A,ull *B,int l,int r){memcpy(A+l,B+l,(r-l+1)<<3);}
void Cro(ull *A,ull *B,int L){for(int i=0;i<L;i++)A[i]=A[i]*B[i]%H;}
void Neg(ull *A,int l,int r){for(int i=l;i<=r;i++)A[i]=!A[i]?0:H-A[i];}
void NTT(ull *p,int L,int op)
{
for(int i=0;i<L;i++)if(i<U[i])swap(p[i],p[U[i]]);
for(int k=2,r=1;k<=L;r=k,k<<=1)
{
ll w=Ksm(op==1?g:ig,(H-1)/k),x;W[0]=1;
for(int i=1;i<=r;i++)W[i]=W[i-1]*w%H;
for(int i=0;i<L;i+=k)for(int l=i;l<i+r;l++)
x=W[l-i]*p[l+r]%H,p[l+r]=p[l]-x+H,p[l]+=x;
if(k==1<<16)for(int i=0;i<L;i++)p[i]%=H;
}
for(int i=0;i<L;i++)p[i]%=H;
if(op==-1)for(ll i=0,j=Ksm(L,H-2);i<L;i++)p[i]=(p[i]*j)%H;
}
void Inv(ull *F,int n)
{
ull G[N],A[N],B[N];G[0]=Ksm(F[0]);int L=1;
while(L<=n)L*=2;
assert(L<=200000);
for(int k=2,r=1;k<=L;r=k,k<<=1)
{
Cpy(A,G,0,r-1);Clr(A,r,k-1);Cpy(B,F,0,k-1);
Init(k);NTT(A,k,1);Cro(A,A,k);NTT(A,k,-1);
Init(k*2);NTT(A,k*2,1);NTT(B,k*2,1);Cro(A,B,k*2);NTT(A,k*2,-1);
Neg(A,r,k-1);Cpy(G,A,r,k-1);
assert(k*2<N);
}
Cpy(F,G,0,n);
}
int n;
ull F[N];
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;n--;
for(int i=0;i<=n;i++)cin>>F[i];
Inv(F,n);
for(int i=0;i<=n;i++)cout<<F[i]<<" ";
}