#include <algorithm>
#include <stdio.h>
#include <vector>
typedef long long llt;
typedef unsigned uint;typedef unsigned long long ullt;
typedef bool bol;typedef char chr;typedef void voi;
typedef double dbl;
template<typename T>bol _max(T&a,T b){return(a<b)?a=b,true:false;}
template<typename T>bol _min(T&a,T b){return(b<a)?a=b,true:false;}
template<typename T>T power(T base,T index,T mod){return((index<=1)?(index?base:1):(power(base*base%mod,index>>1,mod)*power(base,index&1,mod)))%mod;}
template<typename T>T lowbit(T num){return num&-num;}
template<typename T>T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<typename T>T lcm(T a,T b){return(a!=0||b!=0)?a/gcd(a,b)*b:(T)0;}
template<const ullt p=998244353>
class mod_ullt//会自然溢出,模数不可过大
{
private:
ullt v;
voi _print(ullt v){if(v>=10)_print(v/10);putchar('0'+v%10);}
public:
mod_ullt():v(0){}
mod_ullt(ullt v):v(v%p){}
bol empty(){return!v;}
ullt val(){return v;}
bol operator<(mod_ullt b){return v<b.v;}
bol operator>(mod_ullt b){return v>b.v;}
bol operator<=(mod_ullt b){return v<=b.v;}
bol operator>=(mod_ullt b){return v>=b.v;}
bol operator==(mod_ullt b){return v==b.v;}
bol operator!=(mod_ullt b){return v!=b.v;}
bol operator<(ullt v){return*this<mod_ullt(v);}
bol operator>(ullt v){return*this>mod_ullt(v);}
bol operator<=(ullt v){return*this<=mod_ullt(v);}
bol operator>=(ullt v){return*this>=mod_ullt(v);}
bol operator==(ullt v){return*this==mod_ullt(v);}
bol operator!=(ullt v){return*this!=mod_ullt(v);}
mod_ullt operator+(mod_ullt b){return mod_ullt(v+b.v);}
mod_ullt operator+(ullt b){return mod_ullt(v+b%p);}
mod_ullt operator-(mod_ullt b){return mod_ullt(v+p-b.v);}
mod_ullt operator-(ullt b){return mod_ullt(v+p-b%p);}
mod_ullt operator*(mod_ullt b){return mod_ullt(v*b.v);}
mod_ullt operator*(ullt b){return mod_ullt(b%p*v);}
mod_ullt operator/(mod_ullt b){return mod_ullt(v*power(b.v,p-2,p));}
mod_ullt operator/(ullt b){return mod_ullt(v*power(b%p,p-2,p));}
mod_ullt operator-(){return mod_ullt(p-v);}
mod_ullt sqrt()
{
if(power(v,(p-1)>>1,p)!=1)return 0;mod_ullt b=1;do b++;while(b._power((p-1)>>1)==1);ullt t=p-1,s=0,k=1;while(!(t&1))s++,t>>=1;
mod_ullt x=_power((t+1)>>1),e=_power(t);while(k<s){if(e._power(1llu<<(s-k-1))!=1)x*=b._power((1llu<<(k-1))*t);e=_power(p-2)*x*x,k++;}return _min(x,-x),x;
}
mod_ullt inv(){return mod_ullt(power(v,p-2,p));}
mod_ullt _power(ullt index){mod_ullt ans(1),w(v);while(index){if(index&1)ans*=w;w*=w,index>>=1;}return ans;}
voi read(){v=0;chr c;do c=getchar();while(c>'9'||c<'0');do v=c-'0'+v*10,c=getchar();while(c>='0'&&c<='9');v%=p;}
voi print(){_print(v);}
voi println(){_print(v),putchar('\n');}
mod_ullt operator++(int){mod_ullt ans=*this;return*this=*this+1,ans;}
public:
mod_ullt&operator=(ullt v){return this->v=v%p,*this;}
mod_ullt&operator+=(mod_ullt b){return*this=mod_ullt(v+b.v);}
mod_ullt&operator+=(ullt b){return*this=mod_ullt(v+b%p);}
mod_ullt&operator-=(mod_ullt b){return*this=mod_ullt(v+p-b.v);}
mod_ullt&operator-=(ullt b){return*this=mod_ullt(v+p-b%p);}
mod_ullt&operator*=(mod_ullt b){return*this=mod_ullt(v*b.v);}
mod_ullt&operator*=(ullt b){return*this=mod_ullt(b%p*v);}
mod_ullt&operator/=(mod_ullt b){return*this=mod_ullt(v*power(b.v,p-2,p));}
mod_ullt&operator/=(ullt b){return*this=mod_ullt(v*power(b%p,p-2,p));}
mod_ullt&operator++(){return*this=*this+1;}
};
template<const ullt p=998244353>
class Inv_ullt
{
public:
voi bzr(ullt n){V.clear();V.push_back(0);if(n){V.push_back(1);for(ullt i=2;i<=n;++i)V.push_back(-V[p%i]*(p/i));}}
mod_ullt<p>inv(ullt n){return V[n];}mod_ullt<p>operator[](ullt n){return V[n];}std::vector<mod_ullt<p> >I(){return V;}
private:std::vector<mod_ullt<p> >V;
};
template<const ullt p=998244353,const ullt g=3>
class poly_NTT
{
private:
std::vector<mod_ullt<p> >V;
public:
class NTT_ullt
{
public:
uint length(){return len;}
voi bzr(uint length)
{
uint k=0;len=1,V.clear();while(length){++k,len<<=1,length>>=1;}
for(uint i=0;i<len;++i)V.push_back(0);for(uint i=0;i<k;++i)V[1<<i]=1<<(k-i-1);for(uint i=3;i<len;++i)V[i]=V[i^lowbit(i)]|V[lowbit(i)];
}
voi ntt(std::vector<mod_ullt<p> >&x,bol opt)
{
mod_ullt<p>gn,c,tmp;uint m,k;
for(uint i=0;i<len;++i)if(V[i]<i)std::swap(x[i],x[V[i]]);
for(m=2,k=1;m<=len;m<<=1,k<<=1)
{
gn=power(g,(p-1)/m,p);for(uint i=0;i<len;i+=m){c=1;for(uint j=0;j<k;++j,c=c*gn)tmp=x[i+j+k]*c,x[i+j+k]=x[i+j]-tmp,x[i+j]+=tmp;}
}
if(opt){uint l=1,r=len-1;while(l<r)std::swap(x[l++],x[r--]);mod_ullt<p>inv=mod_ullt<p>(len).inv();for(uint i=0;i<len;++i)x[i]*=inv;}
}
private:
std::vector<uint>V;uint len;
};
public:
poly_NTT(){V.clear();}
poly_NTT(std::vector<ullt>V){this->V.clear();for(uint i=0;i<V.size();++i)this->V.push_back(mod_ullt<p>(V[i]));}
poly_NTT(std::vector<mod_ullt<p> >V):V(V){}
bol empty(){return cut_zero(),!size();}
voi bzr(){V.clear();}
voi push(mod_ullt<p>v){V.push_back(v);}
voi push(ullt v){V.push_back(mod_ullt<p>(v));}
voi pop(){V.pop_back();}
mod_ullt<p>val(uint n){return(n<V.size())?V[n]:mod_ullt<p>();}
uint deg(){return V.size()-1;}
uint size(){return V.size();}
poly_NTT operator+(poly_NTT b){uint n=size();if(b.size()<n)b.chg_siz(n);for(uint i=0;i<n;++i)b[i]+=V[i];b.cut_zero();return b;}
poly_NTT operator-(poly_NTT b){uint n=size();if(b.size()<n)b.chg_siz(n);for(uint i=0;i<b.size();++i)b[i]=val(i)-b[i];b.cut_zero();return b;}
poly_NTT operator*(poly_NTT b)
{
if(size()==0)return*this;if(b.size()==0)return b;
std::vector<mod_ullt<p> >v1,v2,v3;NTT_ullt s;uint len;s.bzr(deg()+b.deg()+1),len=s.length();
for(uint i=0;i<len;++i)v1.push_back(val(i)),v2.push_back(b.val(i));s.ntt(v1,0),s.ntt(v2,0);
for(uint i=0;i<len;++i)v3.push_back(v1[i]*v2[i]);s.ntt(v3,1);b=poly_NTT(v3),b.cut_zero();return b;
}
poly_NTT operator*(mod_ullt<p>v){if(empty()||v.empty())return poly_NTT();uint n=size();poly_NTT w=*this;for(uint i=0;i<n;++i)w[i]*=v;return w;}
poly_NTT operator*(const ullt v){return*this*mod_ullt<p>(v);}
poly_NTT operator-(){return*this*(p-1);}
poly_NTT inv(){return inv(size());}
poly_NTT inv(const uint prec)//论文哥常数优化2版本 默认版本
{
std::vector<mod_ullt<p> >ans(prec<<1),f;NTT_ullt s;
ans[0]=V[0].inv();uint tp=1;
while(tp<prec)
{
f.clear(),tp<<=1;for(uint i=0;i<tp;++i)f.push_back(val(i));s.bzr(tp-1),s.ntt(f,0),s.ntt(ans,0);
for(uint i=0;i<tp;++i)f[i]=-f[i]*ans[i]+1;s.ntt(f,1),tp>>=1;for(uint i=0;i<tp;++i)f[i]=f[i+tp],f[i+tp]=0;
s.ntt(f,0);for(uint i=(tp<<1)-1;~i;--i)f[i]*=ans[i];s.ntt(f,1),s.ntt(ans,1);for(uint i=0;i<tp;++i)ans[tp+i]=f[i];tp<<=1;
}
while(ans.size()>prec)ans.pop_back();return ans;
}
poly_NTT diff(){uint n=size();poly_NTT ans;for(uint i=1;i<n;++i)ans.push(V[i]*i);return ans;}
poly_NTT inte(){uint n=size();poly_NTT ans;ans.push(0);Inv_ullt<p>I;I.bzr(n);for(uint i=0;i<n;++i)ans.push(V[i]*I[i+1]);return ans;}
poly_NTT inte(Inv_ullt<p>&I){uint n=size();poly_NTT ans;ans.push(0);for(uint i=0;i<n;++i)ans.push(V[i]*I[i+1]);return ans;}
poly_NTT ln(){return(this->diff()*this->inv()).inte().chg_deg_ed(deg());}
poly_NTT ln(Inv_ullt<p>&I){return(this->diff()*this->inv()).inte(I).chg_deg_ed(deg());}
poly_NTT ln(const uint prec){return(this->diff()*this->inv(prec)).inte().chg_deg_ed(prec-1);}
poly_NTT ln(Inv_ullt<p>&I,const uint prec){return(this->diff()*this->inv(prec)).inte(I).chg_deg_ed(prec-1);}
poly_NTT exp(){return exp(size());}
poly_NTT exp(const uint prec)
{
poly_NTT m,q;m.push(1),q.push(1);if(empty())return m;uint tp=1;Inv_ullt<p>I;I.bzr(prec*2);
while(tp<prec)m*=q+*this-(m.diff()*m.inv(tp<<=1)).inte(I),m.chg_siz(tp);m.chg_siz(prec);return m;
}
poly_NTT exp(Inv_ullt<p>&I){return exp(I,size());}
poly_NTT exp(Inv_ullt<p>&I,const uint prec)
{
poly_NTT m,q;m.push(1),q.push(1);if(empty())return m;uint tp=1;
while(tp<prec)m*=q+*this-(m.diff()*m.inv(tp<<=1)).inte(I),m.chg_siz(tp);m.chg_siz(prec);return m;
}
poly_NTT _power(const ullt index)
{
poly_NTT f,w;if(!index)return f.push(1),f;uint t=0,n=size();while(t<n&&V[t].empty())++t;if(t==n)return*this;
mod_ullt<p>v=V[t].inv();t*=index;if(t>=n)return poly_NTT();
for(uint i=t/index;i<t/index+n-t;++i)w.push(v*V[i]);w=(w.ln()*index).exp(),v=V[t/index]._power(index);
f=std::vector<mod_ullt<p> >(t);for(uint i=t;i<n;i++)f.push(w[i-t]*v);return f;
}
poly_NTT _power(Inv_ullt<p>&I,const ullt index)
{
poly_NTT f,w;if(!index)return f.push(1),f;uint t=0,n=size();while(t<n&&V[t].empty())++t;if(t==n)return*this;
mod_ullt<p>v=V[t].inv();t*=index;if(t>=n)return poly_NTT();
for(uint i=t/index;i<t/index+n-t;++i)w.push(v*V[i]);w=(w.ln(I)*index).exp(I),v=V[t/index]._power(index);
f=std::vector<mod_ullt<p> >(t);for(uint i=t;i<n;i++)f.push(w[i-t]*v);return f;
}
poly_NTT _power(const ullt index1,const ullt index2)//index mod p, index mod (p-1)
{
poly_NTT f,w;uint t=0,n=size();while(t<n&&V[t].empty())++t;if(t==n)return index1?*this:(f.push(1),f);
mod_ullt<p>v=V[t].inv();if(index1==0){f.push(V[t]._power(index2));return f;}t*=index1;if(t>=n)return poly_NTT();
for(uint i=t/index1;i<t/index1+n-t;++i)w.push(v*V[i]);w=(w.ln()*index1).exp(),v=V[t/index1]._power(index2);
f=std::vector<mod_ullt<p> >(t);for(uint i=t;i<n;i++)f.push(w[i-t]*v);return f;
}
poly_NTT sqrt(){return sqrt(size());}
poly_NTT sqrt(const uint prec)
{
if(empty())return poly_NTT();
poly_NTT ans;ans.push(V[0].sqrt());
mod_ullt<p>f=(p+1)>>1;uint tp=1;
while(tp<prec)ans=(ans+ans.inv(tp<<=1)**this)*f,ans.chg_deg(tp);
return ans.chg_siz(prec),ans;
}
poly_NTT reverse(){poly_NTT ans;for(uint i=deg();~i;--i)ans.push(V[i]);return ans;}
poly_NTT operator/(poly_NTT b)
{
cut_zero(),b.cut_zero();uint m=size(),n=b.deg();if(m<=n)return poly_NTT();
poly_NTT f=this->reverse()*b.reverse().inv(m-n);f.chg_siz((m>n)?m-n:0);return f.reverse();
}
poly_NTT operator%(poly_NTT b){poly_NTT f=*this-*this/b*b;f.cut_zero();return f;}
poly_NTT sin(){mod_ullt<>i=mod_ullt<p>(p-1).sqrt();return((*this*-i).exp()-(*this*i).exp())*i*((p+1)>>1);}
poly_NTT cos(){mod_ullt<>i=mod_ullt<p>(p-1).sqrt();return((*this*-i).exp()+(*this*i).exp())*((p+1)>>1);}
voi cut_zero(){while(!V.empty()&&V.back().empty())V.pop_back();}
voi chg_siz(const uint siz){while(V.size()<siz)V.push_back(0);while(V.size()>siz)V.pop_back();}
voi chg_deg(const uint d){chg_siz(d+1);}
poly_NTT chg_deg_ed(const uint d){poly_NTT ans=*this;return ans.chg_deg(d),ans;}
public:
mod_ullt<p>&operator[](const uint n){return V[n];}
poly_NTT&operator=(std::vector<ullt>V){this->V.clear();for(uint i=0;i<V.size();++i)this->V.push_back(mod_ullt<p>(V[i]));return*this;}
poly_NTT&operator=(const std::vector<mod_ullt<p> >V){this->V=V;return*this;}
poly_NTT&operator+=(const poly_NTT b){return*this=*this+b;}
poly_NTT&operator-=(const poly_NTT b){return*this=*this-b;}
poly_NTT&operator*=(const poly_NTT b){return*this=*this*b;}
poly_NTT&operator*=(const mod_ullt<p>b){return*this=*this*b;}
poly_NTT&operator*=(const ullt b){return*this=*this*b;}
poly_NTT&operator/=(const poly_NTT b){return*this=*this/b;}
poly_NTT&operator%=(const poly_NTT b){return*this=*this%b;}
};
poly_NTT<104857601>P,Q;
int main()//以 Luogu P3803 【模板】多项式乘法(FFT) 为例
{
uint n,m;ullt v;scanf("%u%u",&n,&m);
for(uint i=0;i<=n;i++)scanf("%llu",&v),P.push(v);
for(uint i=0;i<=m;i++)scanf("%llu",&v),Q.push(v);
P*=Q;
for(uint i=0;i<=n+m;i++)P[i].print(),putchar((i^(n+m))?' ':'\n');
return 0;
}
| Compilation | N/A | N/A | Compile OK | Score: N/A | 显示更多 |
| Subtask #1 Testcase #1 | 20.41 us | 24 KB | Accepted | Score: 0 | 显示更多 |
| Subtask #1 Testcase #2 | 61.861 ms | 17 MB + 636 KB | Accepted | Score: 100 | 显示更多 |
| Subtask #1 Testcase #3 | 23.624 ms | 8 MB + 980 KB | Accepted | Score: 0 | 显示更多 |
| Subtask #1 Testcase #4 | 23.433 ms | 7 MB + 56 KB | Accepted | Score: 0 | 显示更多 |
| Subtask #1 Testcase #5 | 23.6 us | 24 KB | Accepted | Score: 0 | 显示更多 |
| Subtask #1 Testcase #6 | 21.62 us | 24 KB | Accepted | Score: 0 | 显示更多 |
| Subtask #1 Testcase #7 | 23.16 us | 24 KB | Accepted | Score: 0 | 显示更多 |
| Subtask #1 Testcase #8 | 58.596 ms | 17 MB + 96 KB | Accepted | Score: 0 | 显示更多 |
| Subtask #1 Testcase #9 | 57.872 ms | 15 MB + 976 KB | Accepted | Score: 0 | 显示更多 |
| Subtask #1 Testcase #10 | 54.583 ms | 15 MB + 436 KB | Accepted | Score: 0 | 显示更多 |
| Subtask #1 Testcase #11 | 63.171 ms | 17 MB + 716 KB | Accepted | Score: 0 | 显示更多 |
| Subtask #1 Testcase #12 | 50.651 ms | 16 MB + 596 KB | Accepted | Score: 0 | 显示更多 |
| Subtask #1 Testcase #13 | 17.95 us | 24 KB | Accepted | Score: 0 | 显示更多 |