# 多项式全家桶

## Include

upda：2019.4.28：

1.取消注释 using namespace FastFourierTransform;

2.把//dele start here/* 到// delete end here */ 删除或者注释掉。

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^'0')
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x){
char ch;x=0;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*10+numb);
(fl==true)&&(x=-x);
}
template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');}
//--------------------------------------------------------------------------------------------------------------------//
namespace Miracle{
const int mod;
const int G=3;
const int GI=332748118;
const int I=86583718;
const int iv2=499122177;
const double Pi=acos(-1);
il int qm(int x,int y){int ret=1;while(y){if(y&1) ret=(ll)ret*x%mod;x=(ll)x*x%mod;y>>=1;}return ret;}
il int ad(int x,int y){return x+y>=mod?x+y-mod:x+y;}
il int sub(int x,int y){return ad(x,mod-y);}
il int mul(int x,int y){return (ll)x*y%mod;}
namespace Polynomial{
struct Poly{
vector<int>f;
Poly(){f.clear();}
il int &operator[](const int &x){return f[x];}
il const int &operator[](const int &x) const {return f[x];}
il void resize(const int &n){f.resize(n);}
il int size() const {return f.size();}
il void cpy(Poly &b){f.resize(b.size());for(reg i=0;i<(int)f.size();++i)f[i]=b[i];}
il void rev(){reverse(f.begin(),f.end());}
il void clear(){f.clear();}
il void read(const int &n){f.resize(n);for(reg i=0;i<n;++i)rd(f[i]);}
il void out() const {for(reg i=0;i<(int)f.size();++i)ot(f[i]);putchar('\n');}
}R;
il int init(const int &n){int m;for(m=1;m<n;m<<=1);return m;}
template<class T>il void rev(T &f){
int lp=f.size();
if(R.size()!=f.size()) {
R.resize(f.size());
for(reg i=0;i<lp;++i){
R[i]=(R[i>>1]>>1)|((i&1)?lp>>1:0);
}
}
for(reg i=0;i<lp;++i){
if(i<R[i]) swap(f[i],f[R[i]]);
}
}
}
using namespace Polynomial;
//--------------------------------------------------------------------------------------------------------------------//
il void operator +=(Poly &f,const Poly &g){for(reg i=0;i<f.size();++i) f[i]=ad(f[i],g[i]);}
il void operator +=(Poly &f,const int &c){f[0]=ad(f[0],c);}
il Poly operator +(Poly f,const Poly &g){for(reg i=0;i<f.size();++i) f[i]=ad(f[i],g[i]);return f;}
il Poly operator +(Poly f,const int &c){f[0]=ad(f[0],c);return f;}
il void operator -=(Poly &f,const Poly &g){for(reg i=0;i<f.size();++i) f[i]=sub(f[i],g[i]);}
il void operator -=(Poly &f,const int &c){f[0]=sub(f[0],c);}
il Poly operator -(Poly f,const Poly &g){for(reg i=0;i<f.size();++i) f[i]=sub(f[i],g[i]);return f;}
il Poly operator -(Poly f,const int &c){f[0]=sub(f[0],c);return f;}
il Poly operator -(Poly f){for(reg i=0;i<f.size();++i) f[i]=mod-f[i];return f;}
//--------------------------------------------------------------------------------------------------------------------//
namespace FastFourierTransform{
struct cplx{
double x,y;
cplx(){x=0.0;y=0.0;}
cplx(double xx,double yy){x=xx;y=yy;}
cplx friend operator !(cplx a){return cplx(a.x,-a.y);}
cplx friend operator +(cplx a,cplx b){return cplx(a.x+b.x,a.y+b.y);}
cplx friend operator -(cplx a,cplx b){return cplx(a.x-b.x,a.y-b.y);}
cplx friend operator *(cplx a,cplx b){return cplx(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
};
struct Cps{
vector<cplx>f;
Cps(){f.clear();}
il cplx &operator[](const int &x){return f[x];}
il const cplx &operator[](const int &x) const {return f[x];}
il void resize(const int &n){f.resize(n);}
il int size() const {return f.size();}
il void cpy(Cps &b){f.resize(b.size());for(reg i=0;i<(int)f.size();++i)f[i]=b[i];}
il void rev(){reverse(f.begin(),f.end());}
il void clear(){f.clear();}
il void out(){
for(reg i=0;i<(int)f.size();++i){
cout<<"("<<f[i].x<<","<<f[i].y<<") ";
}cout<<endl;
}
}W;
il void FFT(Cps &f,int c){
int n=f.size();rev(f);
for(reg p=2;p<=n;p<<=1){
int len=p/2;
for(reg l=0;l<n;l+=p){
for(reg k=l;k<l+len;++k){
cplx tmp=f[k+len]*(c>0?W[n/p*(k-l)]:!W[n/p*(k-l)]);
f[k+len]=f[k]-tmp;
f[k]=f[k]+tmp;
}
}
}
if(c==-1){
for(reg i=0;i<n;++i){
f[i].x/=n;f[i].y/=n;
}
}
}
il void prework(int n){
if(W.size()!=n){
W.resize(n);
for(reg i=0;i<n;++i){
W[i]=cplx(cos(2*Pi/n*i),sin(2*Pi/n*i));
}
}
}
il Poly MTT(const Poly &F,const Poly &G,const int &P){
int n=F.size(),m=G.size();
Cps a,b,c,d;
int len=init(n+m-1);
a.resize(len);b.resize(len);
c.resize(len);d.resize(len);
for(reg i=0;i<n;++i){
a[i].x=F[i]>>15;a[i].y=F[i]&32767;
}
for(reg i=0;i<m;++i){
b[i].x=G[i]>>15;b[i].y=G[i]&32767;
}
prework(len);
FFT(a,1);FFT(b,1);
cplx ka,kb,ba,bb;
cplx aaa=cplx(0.5,0),bbb=cplx(0,-0.5),o=cplx(0,1);
for(reg i=0;i<len;++i){
int j=(len-i)%len;
ka=(a[i]+!a[j])*aaa;ba=(a[i]-!a[j])*bbb;
kb=(b[i]+!b[j])*aaa;bb=(b[i]-!b[j])*bbb;
c[i]=ka*kb+ba*kb*o;
d[i]=bb*ka+bb*ba*o;
}
FFT(c,-1);FFT(d,-1);
Poly ret;
ret.resize(n+m-1);
for(reg i=0;i<n+m-1;++i){
ll A=(ll)(c[i].x+0.5)%P,B=(ll)(c[i].y+0.5)%P;
ll C=(ll)(d[i].x+0.5)%P,D=(ll)(d[i].y+0.5)%P;
ret[i]=((((A<<30)%P)+((B+C)<<15)%P)%P+D)%P;
}
return ret;
}
il void operator *=(Poly &f,Poly g){
f=MTT(f,g,mod);
}
il void operator *=(Poly &f,const int &c){for(reg i=0;i<f.size();++i) f[i]=mul(f[i],c);}
il Poly operator *(Poly f,const Poly &g){f*=g;return f;}
il Poly operator *(Poly f,const int &c){for(reg i=0;i<f.size();++i) f[i]=mul(f[i],c);return f;}
il Poly Inv(const Poly &f,int n){
if(n==1){
Poly g;g.resize(1);g[0]=qm(f[0],mod-2);return g;
}
Poly h=Inv(f,(n+1)>>1);
Poly tmp=h,t;
t.resize(n);
for(reg i=0;i<n;++i) t[i]=f[i];
tmp=tmp*tmp*t;
h.resize(tmp.size());
Poly g=h*2-tmp;
g.resize(n);
return g;
}
}
// using namespace FastFourierTransform;
//--------------------------------------------------------------------------------------------------------------------//
// dele start here/*
il void NTT(Poly &f,int c){
int n=f.size();rev(f);
for(reg p=2;p<=n;p<<=1){
int gen=(c==1)?qm(G,(mod-1)/p):qm(GI,(mod-1)/p);
for(reg l=0;l<n;l+=p){
int buf=1;
for(reg k=l;k<l+p/2;++k){
int tmp=mul(f[k+p/2],buf);
f[k+p/2]=sub(f[k],tmp);
f[k]=ad(f[k],tmp);
buf=mul(buf,gen);
}
}
}
if(c==-1){
int iv=qm(n,mod-2);for(reg i=0;i<n;++i) f[i]=mul(f[i],iv);
}
}
il Poly Inv(const Poly &f,int n){
if(n==1){
Poly g;g.resize(1);g[0]=qm(f[0],mod-2);return g;
}
Poly g=Inv(f,(n+1)>>1),t;
int m=init(n*2);
t.resize(m);
for(reg i=0;i<n;++i)t[i]=f[i];
g.resize(m);
NTT(g,1);NTT(t,1);
for(reg i=0;i<m;++i)g[i]=mul(sub(2,mul(g[i],t[i])),g[i]);
NTT(g,-1);g.resize(n);
return g;
}
il void operator *=(Poly &f,Poly g){
int st=f.size()+g.size()-1;
int len=init(f.size()+g.size()-1);f.resize(len);g.resize(len);
NTT(f,1);NTT(g,1);for(reg i=0;i<len;++i) f[i]=mul(f[i],g[i]);
NTT(f,-1);
f.resize(st);
}
il void operator *=(Poly &f,const int &c){for(reg i=0;i<f.size();++i) f[i]=mul(f[i],c);}
il Poly operator *(Poly f,const Poly &g){f*=g;return f;}
il Poly operator *(Poly f,const int &c){for(reg i=0;i<f.size();++i) f[i]=mul(f[i],c);return f;}
// delete end here*/
il Poly operator ~(const Poly &f){return Inv(f,f.size());}
il Poly operator /(Poly f,Poly g){int len=f.size()-g.size()+1;f.rev();g.rev();g.resize(len);f=f*(~g);f.resize(len);f.rev();return f;}
il Poly operator %(Poly f,Poly g){Poly s=f/g;f=f-g*s;f.resize(g.size()-1);return f;}
//--------------------------------------------------------------------------------------------------------------------//
il Poly Inter(Poly f){int st=f.size();f.resize(st+1);for(reg i=st;i>=1;--i){f[i]=mul(f[i-1],qm(i,mod-2));}f[0]=0;return f;}
il Poly Diff(Poly f){int st=f.size();for(reg i=0;i<st-1;++i) f[i]=mul(f[i+1],(i+1));f.resize(st-1);return f;}
il Poly Ln(const Poly &f){Poly g=Diff(f),h=(~f);g=g*h;g.resize(f.size()-1);return Inter(g);}
il Poly Exp(const Poly &f,int n){
if(n==1){
Poly g;g.resize(1);g[0]=1;
return g;
}
Poly g=Exp(f,(n+1)>>1);
g.resize(n);
g=g*(((Ln(g)*(mod-1))+1)+f);
g.resize(n);
return g;
}
il Poly Exp(const Poly &f){
return Exp(f,f.size());
}
il Poly Cos(const Poly &f){
Poly g=Exp(f*I);return (g+(~g))*iv2;
}
il Poly Sin(const Poly &f){
Poly g=Exp(f*I);return (g-(~g))*qm(ad(I,I),mod-2);
}
int main(){

return 0;
}

}
signed main(){
Miracle::main();
return 0;
}

/*
Author: *Miracle*
Date: 2019/4/8 18:57:00
*/

posted @ 2019-04-09 09:04  *Miracle*  阅读(415)  评论(0编辑  收藏  举报