【题目分析】

快速傅里叶变换用于高精度乘法。

其实本质就是循环卷积的计算,也就是多项式的乘法。

两次蝴蝶变换。

二进制取反化递归为迭代。

单位根的巧妙取值,是的复杂度成为了nlogn

范德蒙矩阵计算逆矩阵又减轻了拉格朗日插值法的复杂度。

十分神奇。

【代码】

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath> #include <set>
#include <map>
#include <string>
#include <algorithm>
#include <vector>
#include <iostream>
#include <queue> using namespace std; #define maxn 200005
#define Complex cp
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define mlog 16
#define inf (0x3f3f3f3f) int read()
{
int x=0,f=1; char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
} struct cp{
double x,y;//虚数可表示为 x+y*i i^2=-1
cp operator + (cp a) {return (cp){x+a.x,y+a.y};}
cp operator - (cp a) {return (cp){x-a.x,y-a.y};}
cp operator * (cp a) {return (cp){x*a.x-y*a.y,x*a.y+y*a.x};}
}a[maxn],b[maxn],c[maxn]; double pi=acos(-1.0); // π
int n,m,rev[maxn],len,ans[maxn];
char s[maxn]; void FFT(Complex * x,int n,int f)
{
F(i,0,n-1) if (rev[i]>i) swap(x[rev[i]],x[i]); //构造迭代的形式
for (int m=2;m<=n;m<<=1)
{
Complex wn=(Complex){cos(2.0*pi/m*f),sin(2.0*pi/m*f)}; //当前的主单位根
for (int i=0;i<n;i+=m)
{
Complex w=(Complex){1.0,0};
for (int j=0;j<(m>>1);++j)
{
Complex u=x[i+j],v=x[i+j+(m>>1)]*w;//计算对应的多项式的值
x[i+j]=u+v; x[i+j+(m>>1)]=u-v;
w=w*wn;//在复数域中旋转一个角度
}
}
}
} int main()
{
n=read();
scanf("%s",s); F(i,0,n-1) a[i].x=s[n-1-i]-'0';
scanf("%s",s); F(i,0,n-1) b[i].x=s[n-1-i]-'0';
m=1; n=2*n-1;
while (m<=n) m<<=1,len++; n=m;
F(i,0,n-1)
{
int t=i,ret=0;
F(j,1,len) ret<<=1,ret|=t&1,t>>=1;
rev[i]=ret;
}//二进制翻转,便于化分治为循环迭代
FFT(a,n,1); FFT(b,n,1); //FFT
F(i,0,n-1) c[i]=a[i]*b[i];
FFT(c,n,-1); //IFFT
F(i,0,n-1) ans[i]=(c[i].x/n)+0.5;//精度QAQ
F(i,0,n-1) ans[i+1]+=ans[i]/10,ans[i]%=10;//进位QwQ
n++;
while (!ans[n]&&n) n--;
D(i,n,0) printf("%d",ans[i]);
}

  

05-02 03:53