BZOJ_2179_FFT快速傅立叶_(FFT)
描述
http://www.lydsy.com/JudgeOnline/problem.php?id=2179
超大整数乘法
分析
FFT模板题.
把数字看成是多项式,x是10.然后用FFT做多项式乘法,最后进位就好了.
注意:
1.进位前要把每一位加0.5(或者更小),然后向下取整,应该是浮点数的计算误差吧...
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=140000; 5 const double pi=acos(-1.0); 6 int len; 7 int rev[maxn],ans[maxn]; 8 char str[maxn]; 9 struct cp{//复数(complex) 10 double r,i; 11 cp(double r_=0.0,double i_=0.0):r(r_),i(i_){} 12 cp operator + (const cp &x) const { return cp(r+x.r,i+x.i); } 13 cp operator - (const cp &x) const { return cp(r-x.r,i-x.i); } 14 cp operator * (const cp &x) const { return cp(r*x.r-i*x.i,r*x.i+i*x.r); } 15 }a[maxn],b[maxn],A[maxn]; 16 void brc(int &len){//二进制逆序置换(bit-reverse-copy) 17 memset(rev,-1,sizeof rev); 18 int k=1,l=0; 19 while(k<len) k<<=1,l++; 20 len=k; 21 rev[0]=0; rev[len-1]=len-1; 22 for(int i=1;i<len-1;i++){ 23 if(rev[i]!=-1) continue; 24 int x=i,y=0,m=l; 25 while(m--) y<<=1, y|=(x&1), x>>=1; 26 rev[i]=y; rev[y]=i; 27 } 28 } 29 void dft(cp *a,int n,int flag){//离散傅里叶变换(discrete-Fourier-transform) 30 for(int i=0;i<n;i++) A[rev[i]]=a[i]; 31 for(int i=0;i<n;i++) a[i]=A[i]; 32 for(int m=2;m<=n;m<<=1){ 33 cp wn(cos(2.0*pi/m*flag),sin(2.0*pi/m*flag)); 34 for(int i=0;i<n;i+=m){ 35 cp w(1.0,0.0); int k=m>>1; 36 for(int j=0;j<k;j++){ 37 cp t=w*a[i+j+k], u=a[i+j]; 38 a[i+j]=u+t; 39 a[i+j+k]=u-t; 40 w=w*wn; 41 } 42 } 43 } 44 if(flag==-1)for(int i=0;i<n;i++) a[i].r/=n; 45 } 46 void readin(cp *a){ 47 scanf("%s",str); 48 int l=strlen(str); 49 for(int i=0;i<l;i++) a[i].r=str[l-1-i]-'0'; 50 } 51 int main(){ 52 scanf("%d",&len); 53 len=len*2-1; 54 readin(a); readin(b); 55 brc(len); 56 dft(a,len,1); dft(b,len,1); 57 for(int i=0;i<len;i++) a[i]=a[i]*b[i]; 58 dft(a,len,-1); 59 for(int i=0;i<len;i++) ans[i]=a[i].r+0.5; 60 for(int i=0;i<len;i++) ans[i+1]+=ans[i]/10, ans[i]%=10; 61 len++; 62 while(!ans[len]&&len) len--; 63 for(int i=len;i>=0;i--) printf("%d",ans[i]); 64 return 0; 65 }
2179: FFT快速傅立叶
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 2567 Solved: 1308
[Submit][Status][Discuss]
Description
给出两个n位10进制整数x和y,你需要计算x*y。
Input
第一行一个正整数n。
第二行描述一个位数为n的正整数x。
第三行描述一个位数为n的正整数y。
Output
输出一行,即x*y的结果。
Sample Input
1
3
4
3
4
Sample Output
12
数据范围:
n<=60000
数据范围:
n<=60000