BZOJ2179: FFT快速傅立叶
2179: FFT快速傅立叶
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1314 Solved: 613
[Submit][Status]
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
题解:
感觉FFT理解起来好困难,实现起来也是。。。智商的问题么。。。T_T
代码完全抄袭iwtwiioi神的代码,orz
代码:
1 #include<cstdio> 2 3 #include<cstdlib> 4 5 #include<cmath> 6 7 #include<cstring> 8 9 #include<algorithm> 10 11 #include<iostream> 12 13 #include<vector> 14 15 #include<map> 16 17 #include<set> 18 19 #include<queue> 20 21 #include<string> 22 23 #define inf 1000000000 24 25 #define maxn 200000+5 26 27 #define maxm 20000000+5 28 29 #define eps 1e-10 30 31 #define ll long long 32 33 #define pa pair<int,int> 34 35 #define for0(i,n) for(int i=0;i<=(n);i++) 36 37 #define for1(i,n) for(int i=1;i<=(n);i++) 38 39 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 40 41 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 42 43 #define mod 1000000007 44 45 using namespace std; 46 47 inline int read() 48 49 { 50 51 int x=0,f=1;char ch=getchar(); 52 53 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 54 55 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 56 57 return x*f; 58 59 } 60 struct cp 61 { 62 double x,y; 63 inline cp operator +(cp b){return (cp){x+b.x,y+b.y};} 64 inline cp operator -(cp b){return (cp){x-b.x,y-b.y};} 65 inline cp operator *(cp b){return (cp){x*b.x-y*b.y,x*b.y+y*b.x};} 66 }; 67 const double PI=acos(-1.0); 68 cp a[maxn],b[maxn],c[maxn],y[maxn]; 69 int n,m,len,rev[maxn],ans[maxn]; 70 char s[maxn]; 71 void fft(cp *x,int n,int flag) 72 { 73 for0(i,n-1)y[rev[i]]=x[i]; 74 for0(i,n-1)x[i]=y[i];//翻转 75 for(int m=2;m<=n;m<<=1) 76 { 77 cp wn=(cp){cos(2.0*PI/m*flag),sin(2.0*PI/m*flag)};//w(m,1) 78 for(int i=0;i<n;i+=m)//n个数按m个一份,每份内进行操作 79 { 80 cp w=(cp){1.0,0};int mid=m>>1; 81 for0(j,mid-1) 82 { 83 cp u=x[i+j],v=x[i+j+mid]*w; 84 x[i+j]=u+v;x[i+j+mid]=u-v; 85 w=w*wn; 86 }//蝴蝶操作 87 } 88 } 89 if(flag==-1)for0(i,n-1)x[i].x/=n; 90 } 91 92 int main() 93 94 { 95 96 freopen("input.txt","r",stdin); 97 98 freopen("output.txt","w",stdout); 99 100 n=read(); 101 scanf("%s",s); 102 for0(i,n-1)a[i].x=s[n-1-i]-'0'; 103 scanf("%s",s); 104 for0(i,n-1)b[i].x=s[n-1-i]-'0'; 105 m=1;n=2*n-1; 106 while(m<=n)m<<=1,len++;n=m;//将n修改成2的幂 107 for0(i,n-1) 108 { 109 int t=i,ret=0; 110 for1(j,len)ret<<=1,ret|=t&1,t>>=1;//对这len位的二进制数进行翻转 111 rev[i]=ret;//记录该元素应该到哪个位置 112 } 113 fft(a,n,1);fft(b,n,1); 114 for0(i,n-1)c[i]=a[i]*b[i]; 115 fft(c,n,-1); 116 for0(i,n-1)ans[i]=c[i].x+0.5;//不加0.5会WA 117 for0(i,n-1)ans[i+1]+=ans[i]/10,ans[i]%=10;//进位 118 n++; 119 while(!ans[n]&&n)n--; 120 for3(i,n,0)putchar('0'+ans[i]); 121 122 return 0; 123 124 }