题解 P1919 【【模板】A*B Problem升级版(FFT快速傅里叶)】
斯德哥尔摩
2017-10-21 11:55:22
FFT 板子。。。
注意:
1.最好手写,不然会 TLE
2.FFT 正确食用姿势:系数 - >点值- > 系数
即:(1)如果是fft(a,1)相当于从系数转为点值
(2)如果是fft(b,-1)相当于从点值转为系数
3.利用蝴蝶变换实现迭代版,在代码里面的加速。。。
4.去掉前导零。。。
看代码吧(虽丑):
```cpp
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<math.h>
#include<cmath>
#define N (1<<18)//如果不介意,可以开小点
using namespace std;
struct cmpx{//不一样的结构体,运算符重载
double r,i;
cmpx operator + (const cmpx &a)const{return (cmpx){r+a.r,i+a.i};}
cmpx operator - (const cmpx &a)const{return (cmpx){r-a.r,i-a.i};}
cmpx operator * (const cmpx &a)const{return (cmpx){r*a.r-i*a.i,r*a.i+i*a.r};}
};
int rev[N];
cmpx A[N],a[N],b[N],c[N];
int L,n;
void DFT(cmpx a[],int f){
int i,j,k;
for(i=0;i<L;i++)
A[i]=a[rev[i]];
for(i=0;i<L;i++)
a[i]=A[i];
for(i=2;i<=L;i<<=1){
cmpx wi=(cmpx){cos(2.0*M_PI/i),f*sin(2.0*M_PI/i)};
for(k=0;k<L;k+=i){
cmpx w=(cmpx){1.0,0.0},x,y;
for(j=0;j<i/2;j++){
x=a[k+j];
y=w*a[k+j+i/2];
a[k+j]=x+y;
a[k+j+i/2]=x-y;
w=w*wi;
}
}
}
if(f==-1)
for(i=0;i<L;i++)
a[i].r/=L;
}
void FFT(cmpx a[],cmpx b[],cmpx c[]){
int i;
DFT(a,1);
DFT(b,1);
for(i=0;i<L;i++)
c[i]=a[i]*b[i];
DFT(c,-1);
}
void init(int tmp){
int i,t,j;
for(n=0,L=1;L<tmp;L<<=1)
n++;
n++;
L<<=1;
for(i=0;i<L;i++)
for(t=i,j=0;j<n;j++){
rev[i]<<=1;
rev[i]|=t&1;
t>>=1;
}
}
int ans[N];
void DSC(){//开始处理问题,开始处理问题,开始处理问题,重要的事情说3遍!
int l1=0,l2=0,i;
char ch=getchar();
while(ch>'9'||ch<'0')
ch=getchar();
while(ch>='0'&&ch<='9'){
a[l1].r=ch-'0';
a[l1++].i=0.0;
ch=getchar();
}
while(ch>'9'||ch<'0')
ch=getchar();
while(ch>='0'&&ch<='9'){
b[l2].r=ch-'0';
b[l2++].i=0.0;
ch=getchar();
}
reverse(a,a+l1);
reverse(b,b+l2);
init(max(l1,l2));
FFT(a,b,c);
for(i=0;i<L;i++)
ans[i]=(int)(c[i].r+0.5);
for(i=0;i<L;i++){
ans[i+1]+=ans[i]/10;
ans[i]%=10;
}
L=l1+l2+1;
while(!ans[L]&&L>0)
L--;
for(i=L;~i;i--)
putchar(ans[i]+'0');
putchar('\n');
}
int main(){//主函数so easy
DSC();
return 0;
}
```