您的位置:首页 > 其它

HDU 1402 A*B(FFT 模板题)

2016-11-01 16:27 260 查看
大整数乘法

将每一位数字看做系数,作FFT,变为点值表达,然后再逆变换回去,这时每个系数就是对应结果的十进制位的数,把它变为十进制整数即可

#include <cstdio>
#include <cstring>
#include <queue>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<complex>
#define maxn 140000
using namespace std;
typedef long long LL;
typedef complex<double> CLDD;

const double PI = acos(-1);

CLDD a[maxn],b[maxn],A[maxn],B[maxn];
int ans[maxn];

void strToInt(char * str,int len,CLDD * x)
{
int i = 0;
len--;
while(len>=0){
x[i] = CLDD(str[len]-'0',0);
i++;len--;
}
}
char str[50010];

int rev(int id,int len)
{
int res = 0;
for(int i=0; (1<<i)<len ; ++i)
{
res<<=1;
if(id&(1<<i))res|=1;
}
return res;
}

void FFT(CLDD * c,CLDD* ans,int len,int DFT)
{
for(int i=0 ; i<len ; ++i)
ans[rev(i,len)] = c[i];
for(int s = 1 ; (1<<s)<=len ; ++s)
{
int m = (1<<s);
CLDD wm = CLDD(cos(2*PI*DFT/m),sin(2*PI*DFT/m));
for(int k=0 ; k<len ; k+=m)
{
CLDD w = CLDD(1,0);
for(int j = 0 ; j<(m>>1) ; ++j)
{
CLDD u = ans[k+j];
CLDD t = w*ans[k+j+(m>>1)];
ans[k+j] = u+t;
ans[k+j+(m>>1)] = u-t;
w*=wm;
}
}
}
if(DFT==-1)for(int i=0 ; i<len ; ++i)ans[i]/=len;
}

int main()
{
//freopen("H:\\c++\\file\\stdin.txt","r",stdin);
// int T;scanf("%d",&T);
int sa = 0,sb =0;
while(scanf("%s",str)!=EOF)
{
sa = 0,sb = 0;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(A,0,sizeof(A));
memset(B,0,sizeof(B));
int len = strlen(str);
strToInt(str,len,a);
while((1<<sa)<len)++sa;
scanf("%s",str);
len = strlen(str);
strToInt(str,len,b);
while((1<<sb)<len)++sb;

len = 1<<(max(sb,sa)+1);
FFT(a,A,len,1);

FFT(b,B,len,1);
for(int i = 0 ; i<len ; ++i)
{
A[i]*=B[i];
}
FFT(A,B,len,-1);
for(int i=0 ; i<len ; ++i)
{
// cout<<"ans["<<i<<"]"<<B[i]<<endl;
ans[i] = (int)(B[i].real()+0.2);
}
for(int i=0 ; i<len-1 ; ++i)
{
ans[i+1]+=ans[i]/10;
ans[i]%=10;
}
int start = len-1;
while(start >0 && ans[start]==0)start--;
for(int i = start; i>=0 ; --i)
printf("%d",ans[i]);

putchar('\n');
}
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  fft