30.1 多项式的表达
系数表达: (a0,a1,⋯,an−1)
点值表达: {(x0,y0),(x1,y1),⋯,(xn−1,yn−1)}(yk=A(xk),0≤k≤n−1)
求值(系数表达转换为点值表达, O(n2) ):
霍纳准则: A(x0)=a0+x0(a1+⋯+x0(an−2+x0an−1)⋯)
插值(点值表达转换为系数表达, O(n2) ):
拉格朗日公式: A(x)=∑k=0n−1yk∏j≠k(x−xj)∏j≠k(xk−xj)
30.2 DFT与FFT
y=(y0,y1,⋯,yn−1) 是 a=(a0,a1,⋯,an−1) 的离散傅里叶变换(DFT)。
const double PI=3.141592654;
class Complex
{
public:
Complex(double x=0,double y=0):a(x),b(y){}
friend Complex operator+(Complex x,Complex y)
{
return Complex(x.a+y.a,x.b+y.b);
}
friend Complex operator-(Complex x,Complex y)
{
return Complex(x.a-y.a,x.b-y.b);
}
friend Complex operator*(Complex x,Complex y)
{
return Complex(x.a*y.a-x.b*y.b,x.a*y.b+x.b*y.a);
}
double a,b;
};
//递归
vector<Complex> recursiveFFT(vector<Complex> a)
{
int n=a.size();
if(n==1)return a;
Complex wn(cos(2*PI/n),sin(2*PI/n)),w(1,0);
vector<Complex> a0,a1,y0,y1,y;
for(int i=0;i<n;i+=2)a0.push_back(a[i]);
for(int i=1;i<n;i+=2)a1.push_back(a[i]);
y0=recursiveFFT(a0);
y1=recursiveFFT(a1);
for(int k=0;k<=n/2-1;++k)
{
y[k]=y0[k]+w*y1[k];
y[k+n/2]=y0[k]-w*y1[k];
w=w*wn;
}
return y;
}
T(n)=2T(n/2)+Θ(n)=Θ(nlogn)
30.3 高效FFT实现
//蝴蝶操作
for(int k=0;k<=n/2-1;++k)
{
Complex t=w*y1[k];
y[k]=y0[k]+t;
y[k+n/2]=y0[k]-t;
w=w*wn;
}
//位逆序置换
int rev(int k,int n)
{
int k0=0,m=log((double)n)/log((double)2);
for(int j=0;j<m;++j)
{
if(k&(1<<j))k0+=(1<<(m-1-j));
}
return k0;
}
void bitReverseCopy(vector<Complex> a,vector<Complex> &A)
{
int n=a.size();
for(int k=0;k<=n-1;++k)A[rev(k,n)]=a[k];
}
//迭代
vector<Complex> iterativeFFT(vector<Complex> a)
{
vector<Complex> A;
bitReverseCopy(a,A);
int n=a.size();
for(int s=1;(1<<s)<=n;++s)
{
int m=(1<<s);
Complex wm(cos(2*PI/m),sin(2*PI/m));
for(int k=0;k<=n-1;k+=m)
{
Complex w(1,0);
for(int j=0;j<=m/2-1;++j)
{
Complex u=A[k+j],t=w*A[k+j+m/2];
A[k+j]=u+t;
A[k+j+m/2]=u-t;
w=w*wm;
}
}
}
return A;
}