[bzoj2179]FFT快速傅立叶

来源:互联网 发布:linux top 查看进程 编辑:程序博客网 时间:2024/05/01 02:07

2179: FFT快速傅立叶

Time Limit: 10 Sec  Memory Limit: 259 MB
[Submit][Status][Discuss]

Description

给出两个n位10进制整数x和y,你需要计算x*y。

Input

第一行一个正整数n。 第二行描述一个位数为n的正整数x。 第三行描述一个位数为n的正整数y。

Output

输出一行,即x*y的结果。

Sample Input

1
3
4

Sample Output

12

数据范围:
n<=60000

HINT

fft,裸的
这个板子真的好,相对于丁神的,优化了一些代码长度
抽时间讲一下fft
#include<algorithm>#include<iostream>#include<complex>#include<cstdio>#include<cmath>#define pi acos(-1)using namespace std;const int N = 200000 + 5;typedef complex<double> E;E a[N],b[N]; char ch[N];int n,m,L,c[N],r[N];void fft( E *a, int f ){for( int i = 0; i < n; i++ ) if( i < r[i] ) swap(a[i],a[r[i]]);for( int i = 1; i < n; i <<= 1 ){E wn(cos(pi/i),f*sin(pi/i));for( int j = 0; j < n; j += (i<<1) ){E w(1,0);for( int k = 0; k < i; k++, w *= wn ){E x = a[j+k], y = w*a[j+k+i];a[j+k] = x+y; a[j+k+i] = x-y;}}}if( f == -1 ) for( int i = 0; i < n; i++ ) a[i] /= n;}int main(){scanf("%d", &n); n--;scanf("%s", ch); for( int i = 0; i <= n; i++ ) a[i] = ch[n-i]-'0';scanf("%s", ch); for( int i = 0; i <= n; i++ ) b[i] = ch[n-i]-'0';m = 2*n; for( n = 1; n <= m; n <<= 1 ) L++;for( int i = 0; i < n; i++ ) r[i] = (r[i>>1]>>1) | ((i&1)<<(L-1));fft( a, 1 ); fft( b, 1 );for( int i = 0; i <= n; i++ ) a[i] *= b[i];fft( a, -1 );for( int i = 0; i <= m; i++ ) c[i] = (int)(a[i].real()+0.1);for( int i = 0; i <= m; i++ )if( c[i] >= 10 ){c[i+1] += c[i]/10, c[i] %= 10;if( i == m ) m++;}for( int i = m; i >= 0; i-- ) printf("%d", c[i]);return 0;}