P1919 【模板】A*B Problem升级版(FFT快速傅里叶)
FFT 板子题
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define MAXN 3000100
using namespace std;
char s1[MAXN],s2[MAXN];
int lim=1,r[MAXN],res[MAXN],cnt1,cnt2,k;
const double Pi=acos(-1.0);
struct Node{
double x,y;
Node(double _x=0,double _y=0):x(_x),y(_y){}
Node operator*(Node b){
return Node(x*b.x-y*b.y,x*b.y+y*b.x);
}
Node operator+(Node b){
return Node(x+b.x,y+b.y);
}
Node operator-(Node b){
return Node(x-b.x,y-b.y);
}
}a[MAXN],b[MAXN];
void fft(Node *a,double d){ // d=1:系数转点值,d=-1:点值转系数
for(int i=0;i<lim;i++)if(i<r[i])swap(a[i],a[r[i]]); // butterfly 换位
for(int i=1;i<lim;i<<=1){ // fft 的迭代写法
Node T(cos(Pi/i),d*sin(Pi/i));
for(int j=0;j<lim;j+=(i<<1)){
Node t(1,0);
for(int k=0;k<i;k++,t=t*T){
Node nx=a[j+k],ny=t*a[i+j+k];
a[j+k]=nx+ny;a[i+j+k]=nx-ny;
}
}
}
}
int main(){
#ifdef WINE
freopen("data.in","r",stdin);
#endif
scanf(" %s %s ",s1,s2);
int len1=strlen(s1),len2=strlen(s2);
for(int i=len1-1;i>=0;i--)a[cnt1++].x=s1[i]-'0'; // 从低位到高位存储系数表达式
for(int i=len2-1;i>=0;i--)b[cnt2++].x=s2[i]-'0';
while(lim<len1+len2)lim<<=1,k++; // 通过补零使总长成为2的幂, lim=2^k
for(int i=0;i<lim;i++)r[i]=(r[i>>1]>>1)|((i&1)<<(k-1)); // r[i] 是 i 的反序二进制, 此处写法用了个递推
fft(a,1);fft(b,1); // 系数=>点值
for(int i=0;i<=lim;i++)a[i]=a[i]*b[i]; // 点乘法
fft(a,-1);
int tot=0;
for(int i=0;i<=lim;i++){
res[i]+=(int)(a[i].x/lim+0.5);
if(res[i]>=10)res[i+1]+=res[i]/10,res[i]%=10,lim+=(i==lim);
}
while(!res[lim]&&lim>=1)lim--;lim++;
while(--lim>=0)printf("%d",res[lim]);
return 0;
}