QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#414161 | #1097. 多项式复合 | 11d10xy | 0 | 0ms | 0kb | C++14 | 9.8kb | 2024-05-18 16:09:36 | 2024-05-18 16:09:36 |
Judging History
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%