QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#414161#1097. 多项式复合11d10xy0 0ms0kbC++149.8kb2024-05-18 16:09:362024-05-18 16:09:36

Judging History

This is the latest submission verdict.

  • [2024-05-18 16:09:36]
  • Judged
  • Verdict: 0
  • Time: 0ms
  • Memory: 0kb
  • [2024-05-18 16:09:36]
  • Submitted

answer

#include<bits/stdc++.h>
using namespace std;
using i64=long long;
using poly=vector<i64>;
constexpr i64 mod=998244353;
auto qpow=[](i64 p,i64 t){i64 r=1;for(;t;t>>=1,p=p*p%mod)if(t&1)(r*=p)%=mod;return r;};
auto pls=[](i64 x,i64 y){return x+y>=mod?x+y-mod:x+y;};
auto mns=[](i64 x,i64 y){return x-y<0?x-y+mod:x-y;};
auto getlen=[](int deg){return 1<<__lg(deg)+1;};
auto subpoly=[](const poly&f,int l,int r)->poly{
   r=min((int)f.size(),r),l=max(l,0);
   if(l>=r)return{0};else return poly(begin(f)+l,begin(f)+r);
};
auto revpoly=[](const poly&f){return poly(rbegin(f),rend(f));};
auto shrinkpoly=[](poly&f){for(;f.size()>1&&!f.back();)f.pop_back();};
i64 rp[1<<23],inv[1<<21],fac[1<<21],ifac[1<<21];
int rpn,bn;
void mkrp(int n){
   if(!rpn){rpn=rp[1]=1;}
   while(rpn<n){
      rpn<<=1;i64 w=qpow(3,(mod-1)/rpn);
      for(int i=rpn;i<rpn*2;i+=2)rp[i+1]=(rp[i]=rp[i>>1])*w%mod;
   }
}
void mkbinom(int n){
   if(!bn){fac[0]=fac[1]=1,ifac[0]=ifac[1]=1,inv[1]=1,bn=1;}
   for(int i=bn+1;i<=n;i++)fac[i]=fac[i-1]*i%mod,inv[i]=(mod-mod/i)*inv[mod%i]%mod,ifac[i]=ifac[i-1]*inv[i]%mod;
}
void ntt(poly&f,int n,int inv){
   mkrp(n),f.resize(n);
   i64*a=f.data();
   for(int i=1,r=0;i<n;i++)
   if((r^=n-(n>>__builtin_ffs(i)))>i)swap(a[i],a[r]);
   for(int h=1;h<n;h<<=1)for(i64*i=a;i!=a+n;i+=h*2)for(i64*j=i,*p=rp+h*2,x,y;j!=i+h;j++,p++)
   x=j[0],y=j[h]**p%mod,j[0]=pls(x,y),j[h]=mns(x,y);
   if(inv==-1){
      i64 i=qpow(n,mod-2);
      for(i64&x:f)(x*=i)%=mod;
      reverse(a+1,a+n);
   }
}
poly mul(poly f,poly g,int N=0){
   int n=getlen(f.size()+g.size()-1);
   ntt(f,n,1),ntt(g,n,1);
   for(int i=0;i<n;i++)(f[i]*=g[i])%=mod;
   ntt(f,n,-1),shrinkpoly(f);
   if(N)f.resize(N);
   return f;
}
poly add(poly f,poly g){
   if(f.size()<g.size())swap(f,g);
   for(int i=0;i<g.size();i++)f[i]=pls(f[i],g[i]);
   for(;f.size()>1&&!f.back();f.pop_back());
   return f;
}
poly iadd(poly f,poly g){
   if(f.size()<g.size())f.resize(g.size());
   for(int i=0;i<g.size();i++)f[i]=mns(f[i],g[i]);
   for(;f.size()>1&&!f.back();f.pop_back());
   return f;
}
poly kmul(i64 k,poly f){
   for(i64&x:f)(x*=k)%=mod;
   return f;
}
poly Der(poly f){
   for(int i=1;i<f.size();i++)f[i-1]=f[i]*i%mod;
   f.pop_back();return f;
}
poly Int(poly f){//??????push_back(f.back()*n^{-1})
   int n=f.size();
   mkbinom(n);
   for(int i=n-1;i>0;i--)f[i]=f[i-1]*inv[i]%mod;
   f[0]=0;return f;
}
void next_inv(poly&f,poly&g,int nexn){
   int m=nexn*2;
   poly x=subpoly(f,0,nexn);
   ntt(g,m,1),ntt(x,m,1);
   for(int i=0;i<m;i++)g[i]=g[i]*mns(2,g[i]*x[i]%mod)%mod;
   ntt(g,m,-1),g.resize(nexn);
}
poly ipoly(poly f,int n){
   poly g{qpow(f[0],mod-2)};
   for(int h=1;h<n;next_inv(f,g,h<<=1));
   g.resize(n);
   return g;
}
poly sqrtpoly(poly f,int n){
   poly g{1},ig{1};
   for(int h=1;h<n;h<<=1){
      poly x=ig;next_inv(g,x,h*2);
      g=kmul(mod+1>>1,add(mul(subpoly(f,0,h*2),x),g)),g.resize(h*2);
      next_inv(g,ig,h*2);
   }g.resize(n);
   return g;
}
poly lnbyinv(poly f,poly i,int n){
   f=mul(Der(f),i),f.resize(n);
   return Int(f);
}
poly lnpoly(poly f,int n){
   return lnbyinv(f,ipoly(f,n),n);
}
poly exppoly(poly f,int n){
   poly g{1},ig{1};
   for(int h=1;h<n;h<<=1){
      int m=h*2,k=m*2;
      poly x=ig,y=subpoly(f,0,m);
      next_inv(g,x,m),x=lnbyinv(g,x,m);
      ntt(x,k,1),ntt(y,k,1),ntt(g,k,1);
      for(int i=0;i<k;i++)g[i]=g[i]*pls(mns(1,x[i]),y[i])%mod;
      ntt(g,k,-1),g.resize(m),next_inv(g,ig,m);
   }g.resize(n);
   return g;
}
poly sinpoly(poly f,int n){
   i64 w=qpow(3,(mod-1)/4);
   return kmul(qpow(w*2%mod,mod-2),iadd(exppoly(kmul(w,f),n),exppoly(kmul(mod-w,f),n)));
}
poly cospoly(poly f,int n){
   i64 w=qpow(3,(mod-1)/4);
   return kmul(mod+1>>1,add(exppoly(kmul(w,f),n),exppoly(kmul(mod-w,f),n)));
}
poly powpoly(poly f,i64 t,int n){
   if(!t){poly g(n);g[0]=1;return g;}
   int d;
   for(d=0;d<f.size()&&!f[d];d++);
   if(d==f.size()||d*t>=n)return poly(n,0);
   i64 v=f[d];
   f.erase(begin(f),begin(f)+d);
   f=exppoly(kmul(t,lnpoly(kmul(qpow(v,mod-2),f),n)),n),f.insert(begin(f),d*t,0),f.resize(n);
   return kmul(qpow(v,t),f);
}
poly powpoly2(poly f,i64 g0,i64 w,int n){
   return kmul(g0,exppoly(kmul(w,lnpoly(kmul(qpow(f[0],mod-2),f),n)),n));
}
struct polydiv{
   poly q,r;
   polydiv(poly f,poly g){
      shrinkpoly(f),shrinkpoly(g);
      if(f.size()<g.size()){q={0},r=f;return;}
      int k=f.size()-g.size()+1;
      q=revpoly(mul(subpoly(revpoly(f),0,k),ipoly(revpoly(g),k),k)),
      r=iadd(f,mul(q,g));
   }
};
struct Eval{
   poly x,y;
   map<pair<int,int>,poly>T;
   void f0(int l,int r){
      if(l==r){T[{l,r}]={mod-x[l],1};return;}
      int mid=l+r>>1;
      f0(l,mid),f0(mid+1,r);
      T[{l,r}]=mul(T[{l,mid}],T[{mid+1,r}]);
   }
   void f1(poly F,poly G,const poly&o,int l,int r){
      int k=(int)F.size()-(r-l+2)+1,i=max(k,r-l+2);
      if(!o.empty())G.resize(i),G=mul(revpoly(o),G,i);
      if(k>0)F=iadd(F,mul(revpoly(mul(subpoly(revpoly(F),0,k),G,k)),T[{l,r}]));
      if(l==r){y[l]=F[0];return;}
      int mid=l+r>>1;
      f1(F,G,T[{mid+1,r}],l,mid),f1(F,G,T[{l,mid}],mid+1,r);
   }
   void A(poly _){x=_;f0(0,x.size()-1);}
   void B(poly a){
      y.resize(x.size());
      int n=x.size();
      int k=(int)a.size()-n+1;
      poly f=ipoly(revpoly(T[{0,n-1}]),max(n+3>>1,k));
      if(k>0)a=iadd(a,mul(T[{0,n-1}],revpoly(mul(subpoly(revpoly(a),0,k),subpoly(f,0,k),k))));
      f.resize(n+3>>1);
      f1(a,f,{},0,n-1);
   }
   Eval(poly a,poly _){A(_),B(a);}
   Eval(){}
};
struct Qip{
   poly X,Y;
   Eval E;
   void tell(i64 x,i64 y){X.push_back(x),Y.push_back(y);}
   poly f(int l,int r){
      if(l==r)return{Y[l]};
      int mid=l+r>>1;
      return add(mul(f(l,mid),E.T[{mid+1,r}]),mul(f(mid+1,r),E.T[{l,mid}]));
   }
   poly res(){
      E.A(X),E.B(Der(E.T[{0,X.size()-1}]));
      for(int i=0;i<Y.size();i++)(Y[i]*=qpow(E.y[i],mod-2))%=mod;
      return f(0,X.size()-1);
   }
};
struct poly2D{
   vector<poly>f;
   poly2D(int r,int c){resize(r,c);}
   int rown(){return f.size();}
   int coln(){return f[0].size();}
   void resize(int r,int c){
      if(r!=-1)f.resize(r,poly(c==-1?coln():c));
      f.shrink_to_fit();
      if(c!=-1)for(auto&g:f)g.resize(c),g.shrink_to_fit();
   }
   poly&operator[](int r){return f[r];}
   void ntt2D(int n,int m,int iv){
      resize(n,m);
      for(int i=0;i<n;i++)ntt(f[i],m,iv);
      for(int j=0;j<m;j++){
         poly g(n);
         for(int i=0;i<n;i++)g[i]=f[i][j];
         ntt(g,n,iv);
         for(int i=0;i<n;i++)f[i][j]=g[i];
      }
   }
   void shrink(){
      while(f.size()>1){
         bool x=true;for(i64 _:f.back())x&=!_;
         if(!x)break;f.pop_back();
      }
      while(f[0].size()>1){
         bool x=true;
         for(auto&_:f)x&=!_.back();
         if(!x)break;
         for(auto&_:f)_.pop_back();
      }
   }
};
// poly2D mul2D(poly2D f,poly2D g){
//    int N=getlen(f.rown()+g.rown()-1),M=getlen(f.coln()+g.coln()-1);
//    f.ntt2D(N,M,1),g.ntt2D(N,M,1);
//    for(int i=0;i<N;i++)for(int j=0;j<M;j++)
//    (f[i][j]*=g[i][j])%=mod;
//    f.ntt2D(N,M,-1),f.shrink();
//    return f;
// }
poly2D mul2D(poly2D f,poly2D g){
   int N=f.rown()+g.rown()-1,M=f.coln()+g.coln()-1;
   poly2D h(N,M);
   poly f_(N*M),g_(N*M);
   for(int i=0;i<f.rown();i++)for(int j=0;j<f.coln();j++)
   f_[i*M+j]=f[i][j];
   for(int i=0;i<g.rown();i++)for(int j=0;j<g.coln();j++)
   g_[i*M+j]=g[i][j];
   f_=mul(f_,g_,N*M);
   for(int i=0;i<N;i++)for(int j=0;j<M;j++)h[i][j]=f_[i*M+j];
   return h;
}
poly xnfrac2D(i64 n,poly2D P,poly2D Q){//[x^n]P/Q
   for(;n;n>>=1){
      if(P.rown()>n+1)P.resize(n+1,-1);
      if(Q.rown()>n+1)Q.resize(n+1,-1);
      auto H=Q;
      for(int i=1;i<H.rown();i+=2)for(i64&x:H[i])x=mns(0,x);
      P=mul2D(P,H),Q=mul2D(Q,H);
      for(int i=0;;i++)if(i*2<Q.rown())Q[i]=Q[i*2];else
      {Q.resize(i,-1);break;}
      for(int i=0,j;;i++)if((j=i*2+(n&1))<P.rown())P[i]=P[j];else
      {P.resize(i,-1);break;}
   }
   return polydiv(P[0],Q[0]).q;//I think jue dui ke yi zhengchu
}
poly ipoly2(poly f,int n){
   //[x^n]f^k=k/n [u^{n-k}](u/g)^n  k=0...n
   poly2D p(1,1),q(n,2);
   p[0][0]=1,q[0][0]=1;
   for(int i=1;i<n;i++)q[i][1]=mns(0,f[i]);
   poly g=xnfrac2D(n,p,q);g.resize(n+1);
   //[x^n]f^n=f[0]^n\to g.size()==n
   //bu xu yao g0,yin ci ke yi cheng inv0 
   mkbinom(n);
   for(int k=0;k<=n;k++)(g[k]*=n*inv[k]%mod)%=mod;
   g=powpoly2(revpoly(g),qpow(f[1],mod-2),mod-qpow(n,mod-2),n),g.insert(begin(g),0),g.resize(n);
   return g;
}
struct ___COMP_T{
   poly f,g;
   poly2D calc(int n,int m,poly2D q){//n biao shi mod x^n,m biao shi deg_y(q)=m
      /*shi ji yi F y^{2m-1} de xing shi bao cun*/
      /*fan hui de shi hou bao liu y^{-m+1}...y^0*/
      poly2D r(n,m);
      if(n==1){
         f.resize(m),reverse(begin(f),end(f));
         poly _(m);
         _[0]=1,mkbinom(m);
         for(int i=1;i<m;i++)_[i]=_[i-1]*g[0]%mod*(m+i-1)%mod*inv[i]%mod;
         r[0]=mul(f,_,m);
         return r;
      }q.resize(n,m+1);
      poly2D iq=q;
      for(int i=1;i<iq.rown();i+=2)for(i64&x:iq[i])x=mns(0,x);
      q=mul2D(q,iq);
      for(int i=0;;i++)if(i*2<n)q[i]=q[i*2];else
      {q.resize(i,-1);break;}
      q=calc((n+1)/2,m*2,q),q.resize(n,-1);
      for(int i=n-1;i>=0;i--)if(i&1)for(i64&x:q[i])x=0;else q[i]=q[i/2];
      q=mul2D(q,iq);
      for(int i=0;i<n;i++)copy_n(begin(q[i])+m,m,begin(r[i]));
      return r;
   }
};
poly comppoly(poly f,poly g,int n){
   ___COMP_T __{f,g};
   g.resize(n);
   poly2D h(n,2);h[0][0]=1;
   for(int i=0;i<n;i++)h[i][1]=mns(0,g[i]);
   h=__.calc(n,1,h);
   for(int i=0;i<n;i++)g[i]=h[i][0];
   return g;
}
int main(){
   int n,m;
   cin>>n>>m;
   poly f(n),g(m);
   for(i64&x:f)scanf("%lld",&x);
   for(i64&x:g)scanf("%lld",&x);
   for(i64 x:comppoly(f,g,n))printf("%lld ",x);
   return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Subtask #1:

score: 0
Time Limit Exceeded

Test #1:

score: 0
Time Limit Exceeded

input:

10
471718462 333538257 428598195 612052692 590471745 944446044 697100922 914821505 821922667 796204008
0 664524145 888781513 683400052 974162045 247468747 989741728 584905990 907760865 369079177

output:


result:


Subtask #2:

score: 0
Skipped

Dependency #1:

0%

Subtask #3:

score: 0
Skipped

Dependency #1:

0%

Subtask #4:

score: 0
Skipped

Dependency #1:

0%

Subtask #5:

score: 0
Skipped

Dependency #1:

0%

Subtask #6:

score: 0
Skipped

Dependency #1:

0%

Subtask #7:

score: 0
Skipped

Dependency #1:

0%

Subtask #8:

score: 0
Skipped

Dependency #1:

0%

Subtask #9:

score: 0
Skipped

Dependency #1:

0%

Subtask #10:

score: 0
Skipped

Dependency #1:

0%