HDU 1402 FFT

题目: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;  
} 

猜你喜欢

转载自blog.csdn.net/qq_38987374/article/details/80077921