题目:http://acm.hdu.edu.cn/showproblem.php?pid=1402
这是第一次接触FFT。首先来认识一下。
FFT全名Fast Fourier Transformation FFT
快速傅里叶变换的意思。
这个算法的具体实现其实并不清楚。但是主要用途还是知道的。
用来将O(n*n)复杂的两等式相乘。变成O(n*logn)。
这题就真是一道裸模板题。啥都不用改。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <map>
#include <queue>
#include <vector>
#define PI 3.1415926
#define INF 1e18
#define inf 1e9
#define min(a,b) a<b?a:b
#define max(a,b) a>b?a:b
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define IOS ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std ;
typedef long long ll;
typedef unsigned long long ull;
// 这一大坨fft的代码实现不要动的
const double pi = acos(-1.0);
struct Complex {
double x, y;
Complex(double _x = 0.0, double _y = 0.0) {
x = _x;
y = _y;
}
Complex operator - (const Complex &b)const {
return Complex(x-b.x, y-b.y);
}
Complex operator + (const Complex &b)const {
return Complex(x+b.x, y+b.y);
}
Complex operator * (const Complex &b)const {
return Complex(x*b.x-y*b.y, x*b.y+y*b.x);
}
};
void change(Complex y[], int len) {
int i, j, k;
for(i = 1, j = len/2; i < len-1; i++) {
if (i < j) swap(y[i], y[j]);
k = len/2;
while(j >= k) {
j -= k;
k /= 2;
}
if (j < k) j += k;
}
}
void fft(Complex y[], int len, int on) {
change(y, len);
for(int h = 2; h <= len; h <<= 1) {
Complex wn(cos(-on*2*pi/h), sin(-on*2*pi/h));
for(int j = 0; j < len; j += h) {
Complex w(1, 0);
for(int k = j; k < j+h/2; k++) {
Complex u = y[k];
Complex t = w*y[k+h/2];
y[k] = u+t;
y[k+h/2] = u-t;
w = w*wn;
}
}
}
if (on == -1)
for(int i = 0; i < len; i++)
y[i].x /= len;
}
//到这里
//下面这些数组的大小不是乱开的,下面会讲
const int MAXN = 50002;
ll num[MAXN<<2];//保存结果的数组,要开4*MAXN
Complex x1[MAXN<<2], x2[MAXN<<2];//模板里需要的数组,也要开4*MAXN
char str1[MAXN], str2[MAXN];
int main() {
//freopen("in.txt", "r", stdin);
while (scanf("%s%s", str1, str2) == 2) {
int ls1 = strlen(str1), ls2 = strlen(str2);
int len = 1;
//下面也是模板,别问为什么就是这样的
while (len < 2*ls1 || len < 2*ls2) len <<= 1;//上面数组的大小是因为这里
int i;
for(i = 0; i < ls1; i++) {
x1[i] = Complex(str1[ls1-i-1]-'0', 0);
}
for(; i < len; i++)
x1[i] = Complex(0, 0);
fft(x1, len, 1);
for(i = 0; i < ls2; i++) {
x2[i] = Complex(str2[ls2-i-1]-'0', 0);
}
for(; i < len; i++)
x2[i] = Complex(0, 0);
fft(x2, len, 1);
for(i = 0; i < len; i++)
x1[i] = x1[i]*x2[i];
fft(x1, len, -1);
for(i = 0; i < len; i++) {
num[i] = (ll)(x1[i].x+0.5);
}
//到这里num里面保存的就是结果
for(i = 0; i < len; i++) { //进位
num[i+1] += num[i]/10;
num[i] %= 10;
}
len = ls1+ls2-1;
while(num[len] <= 0 && len > 0) len--;//去前置零;
for(i = len; i >= 0; i--)
printf("%I64d", num[i]);
puts("");
}
return 0;
}