hdu 1402 A * B Problem Plus 【快速傅里叶变换FFT】
http://acm.hdu.edu.cn/showproblem.php?pid=1402
这道题用FFT解决大数乘法问题,比字符串模拟的大数乘法效率要高,听说还有更加快的数论解法;
马上就要学快速福利叶变换了,到时候再补充题解
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <set> #include <map> #include <cmath> #include <queue> using namespace std; template <class T> void checkmin(T &t,T x) {if(x < t) t = x;} template <class T> void checkmax(T &t,T x) {if(x > t) t = x;} template <class T> void _checkmin(T &t,T x) {if(t==-1) t = x; if(x < t) t = x;} template <class T> void _checkmax(T &t,T x) {if(t==-1) t = x; if(x > t) t = x;} typedef pair <int,int> PII; typedef pair <double,double> PDD; typedef long long ll; #define foreach(it,v) for(__typeof((v).begin()) it = (v).begin(); it != (v).end ; it ++) const double Pi = acos(-1.0); const int N = 200020; struct vir { double re , im; vir(double a=0,double b=0) {re=a;im=b;} vir operator + (const vir &b) {return vir(re+b.re,im+b.im);} vir operator - (const vir &b) {return vir(re-b.re,im-b.im);} vir operator * (const vir &b) {return vir(re*b.re-im*b.im,re*b.im+im*b.re);} }; vir x1[N] , x2[N]; void change(vir *x,int len,int loglen) { int i , j , k , t; for(i=0;i<len;i++) { t = i; for(j=k=0;j<loglen;j++,t>>=1) k=(k<<1)|(t&1); if(k < i) { vir tt = x[k]; x[k] = x[i]; x[i] = tt; } } } void fft(vir *x,int len,int loglen) { change(x , len , loglen); for(int i=0,t=1;i<loglen;i++,t<<=1) { int s = 0 , e = s + t; while(s < len) { vir a , b , wo(cos(Pi/t),sin(Pi/t)),wn(1,0); for(int j=s;j<s+t;j++) { a = x[j]; b = x[j+t] * wn; x[j] = a+b; x[j+t] = a-b; wn = wn * wo; } s = e + t; e = s + t; } } } void dit_fft(vir *x,int len,int loglen) { for(int i=0,s,e,t=1<<loglen;i<loglen;i++) { t>>=1; s=0; e=s+t; while(s < len) { vir a , b , wn(1,0) , wo(cos(Pi/t),-sin(Pi/t)); for(int j=s;j<s+t;j++) { a=x[j]+x[j+t];b=(x[j]-x[j+t])*wn; x[j] = a; x[j+t] = b; wn = wn*wo; } s = e + t; e = s + t; } } change(x , len , loglen); for(int i=0;i<len;i++) x[i].re /= len; } void solve(char *a,char *b) { int i,len1,len2,len,loglen; int t , over; len1 = strlen(a)<<1 ; len2 = strlen(b)<<1; len = 1 ; loglen = 0; while(len < len1) len<<=1,loglen++; while(len < len2) len<<=1,loglen++; // init for(i=0;a[i];i++) x1[i].re=a[i]-'0',x1[i].im=0; for(;i<len;i++) x1[i].re=x1[i].im=0; for(i=0;b[i];i++) x2[i].re=b[i]-'0',x2[i].im=0; for(;i<len;i++) x2[i].re=x2[i].im=0; fft(x1,len,loglen); fft(x2,len,loglen); for(i=0;i<len;i++) x1[i]=x1[i]*x2[i]; dit_fft(x1,len,loglen); //将x1.re从浮点数转化为十进制整型存入a for(i=(len1+len2)/2-2,over=len=0;i>=0;i--) { t=x1[i].re+over+0.5; a[len++] = t % 10; over = t / 10; } while(over) { a[len++] = over % 10; over /= 10; } // output for(len--;len>=0&&!a[len];len--); if(len < 0) putchar('0'); else for(;len>=0;len--) putchar(a[len]+'0'); puts(""); } int main() { char a[N] , b[N]; while(~scanf("%s%s",a,b)) { solve(a , b); } return 0; }