终于把多项式板子打完啦!
最后补充一点三角函数的芝士
求
cos
F
\cos F
cosF与
sin
F
\sin F
sinF
想到伟大的欧拉公式!
e
θ
i
=
cos
θ
+
i
sin
θ
e^{\theta i}=\cos \theta +i\sin \theta
eθi=cosθ+isinθ
θ
\theta
θ看成多项式一样的
推柿子
得到:
cos
F
=
e
F
i
+
e
−
F
i
2
sin
F
=
e
F
i
−
e
−
F
i
2
i
\cos F=\frac{e^{Fi}+e^{-Fi}}{2}\\ \sin F=\frac{e^{Fi}-e^{-Fi}}{2i}
cosF=2eFi+e−FisinF=2ieFi−e−Fi
有点难搞的就只剩虚单位
i
i
i了!
虚单位。。。虚单位根?
妙啊!
联想丑陋的FFT
i
i
i是
w
4
w_4
w4,有
i
4
=
1
i^4=1
i4=1
模意义下呢?
x
4
≡
1
x^4\equiv 1
x4≡1
x
=
g
m
o
d
−
1
4
x=g^{\frac{mod-1}{4}}
x=g4mod−1
完美
下面看下石室中学秘传板子
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> poly;
#define cs const
#define pb push_back
#define in Read()
int in{
int i=0,f=1;char ch=0;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') ch=getchar(),f=-1;
while(isdigit(ch)) i=(i<<1)+(i<<3)+ch-48,ch=getchar();
return i*f;
}
cs int mod=998244353,N=5e6+5;
int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
int dec(int a,int b){return a<b?a-b+mod:a-b;}
int mul(int a,int b){return 1ll*a*b%mod;}
int qpw(int a,int b){
int res=1;
while(b){
if(b&1) res=mul(res,a);
a=mul(a,a);
b>>=1;
}
return res;
}
cs int inv2=mod+1>>1;
void print(cs poly &f){
for(int i=0;i<f.size();++i)
printf("%d ",f[i]);
return;
}
int rev[N],inv[N],fac[N],ifac[N],lim;
void init(int deg){
lim=1;
while(lim<deg) lim<<=1;
for(int i=0;i<lim;++i)
rev[i]=(rev[i>>1]>>1)|((i&1)?lim>>1:0);
return;
}
void init_inv(int len){
fac[0]=fac[1]=ifac[0]=ifac[1]=1;
for(int i=1;i<=len;++i) fac[i]=mul(fac[i-1],i);
ifac[len]=qpw(fac[len],mod-2);
for(int i=len-1;i;--i) ifac[i]=mul(ifac[i+1],i+1);
for(int i=1;i<=len;++i) inv[i]=mul(ifac[i],fac[i-1]);
return;
}
void NTT(poly &f,int sgn){
for(int i=0;i<lim;++i)
if(i<rev[i]) swap(f[i],f[rev[i]]);
for(int len=1;len<lim;len<<=1){
int siz=len<<1;
int wn=qpw(3,(mod-1)/siz);
for(int l=0;l<lim;l+=siz){
int w=1;
for(int i=l;i<l+len;++i){
int a=f[i],b=mul(f[i+len],w);
f[i]=add(a,b);
f[i+len]=dec(a,b);
w=mul(w,wn);
}
}
}
if(sgn) return;
int INV=qpw(lim,mod-2);
reverse(f.begin()+1,f.end());
for(int i=0;i<lim;++i)
f[i]=mul(f[i],INV);
return;
}
poly operator + (poly f,poly g){
f.resize(max(f.size(),g.size()));
for(int i=0;i<g.size();++i)
f[i]=add(f[i],g[i]);
return f;
}
poly operator - (poly f,poly g){
f.resize(max(f.size(),g.size()));
for(int i=0;i<g.size();++i)
f[i]=dec(f[i],g[i]);
return f;
}
poly operator * (poly a,poly b){
int deg=a.size()+b.size()-1;
if(a.size()<=32||b.size()<=32){
poly c(deg,0);
for(int i=0;i<a.size();++i)
for(int j=0;j<b.size();++j)
c[i+j]=add(c[i+j],mul(a[i],b[j]));
return c;
}
init(deg);
a.resize(lim),NTT(a,1);
b.resize(lim),NTT(b,1);
for(int i=0;i<lim;++i) a[i]=mul(a[i],b[i]);
NTT(a,0);
a.resize(deg);
return a;
}
poly operator * (poly a,int b){
for(int i=0;i<a.size();++i)
a[i]=mul(a[i],b);
return a;
}
poly der(poly f){
for(int i=0;i<f.size()-1;++i)
f[i]=mul(f[i+1],i+1);
f.pop_back();
return f;
}
poly Int(poly f){
f.pb(0);
for(int i=f.size()-1;i;--i)
f[i]=mul(f[i-1],inv[i]);
f[0]=0;
return f;
}
void divx(poly &f,int cnt){
int deg=f.size()-cnt;
for(int i=0;i<deg;++i) f[i]=f[i+cnt];
f.resize(deg);
return;
}
void mulx(poly &f,int cnt){
int deg=f.size()+cnt;
f.resize(deg);
for(int i=cnt;i<deg;++i) f[i]=f[i-cnt];
for(int i=0;i<cnt;++i) f[i]=0;
return;
}
poly Inv(cs poly &a,int siz){
poly c,b(1,qpw(a[0],mod-2));
for(int len=2;(len>>1)<siz;len<<=1){
init(len<<1);
c=a,c.resize(len);
c.resize(lim),NTT(c,1);
b.resize(lim),NTT(b,1);
for(int i=0;i<lim;++i) b[i]=mul(b[i],dec(2,mul(c[i],b[i])));
NTT(b,0);
b.resize(len);
}
b.resize(siz);
return b;
}poly Inv(cs poly &a){return Inv(a,a.size());}
poly ln(poly a,int len){
a=Int(der(a)*Inv(a,len));
a.resize(len);
return a;
}poly ln(cs poly &a){return ln(a,a.size());}
poly exp(cs poly &a,int siz){
poly c,b(1,1);
for(int len=2;(len>>1)<siz;len<<=1){
c=ln(b,len);
for(int j=0;j<len;++j) c[j]=dec(j<a.size()?a[j]:0,c[j]);
c[0]=add(c[0],1);
b=b*c;
b.resize(len);
}
b.resize(siz);
return b;
}poly exp(cs poly &a){return exp(a,a.size());}
poly qpw(poly a,int k,int len){
a=exp(ln(a)*k);
a.resize(len);
return a;
}poly qpw(cs poly &a,int k){return qpw(a,k,a.size());}
poly sqrt(cs poly &a,int deg){
poly b(1,1),c,d;
for(int len=2;(len>>1)<deg;len<<=1){
init(len<<1);
c=a,c.resize(len);
d=Inv(b,len);
c=c*d;
b.resize(len);
for(int i=0;i<len;++i) b[i]=mul(add(c[i],b[i]),inv2);
}
b.resize(deg);
return b;
}poly sqrt(cs poly &a){return sqrt(a,a.size());}
poly operator / (poly a,poly b){
int deg=a.size()-b.size()+1;
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
init(deg);
b=Inv(b,lim);b.resize(deg);
a=a*b;a.resize(deg);
reverse(a.begin(),a.end());
return a;
}
poly operator % (cs poly &a,cs poly &b){
poly c=a-(a/b)*b;
c.resize(b.size()-1);
return c;
}
cs int w4=qpw(3,(mod-1)/4);
poly cos(cs poly &a,int siz){
poly c=a;c.resize(siz);
c=(exp(c*w4)+exp(c*(mod-w4)))*inv2;
return c;
}poly cos(cs poly &a){return cos(a,a.size());}
poly sin(cs poly &a,int siz){
poly c=a;c.resize(siz);
c=(exp(c*w4)-exp(c*(mod-w4)))*mul(inv2,qpw(w4,mod-2));
return c;
}poly sin(cs poly &a){return sin(a,a.size());}