bzoj2179 FFT快速傅立叶

2179: FFT快速傅立叶

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 4155  Solved: 2222
[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
分析:终于把fft给学了. 推荐一篇文章:传送门
 
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;
const int maxn = 2e5+5;
const double pai = acos(-1.0);

int len1,len2,len,res[maxn];
char s1[maxn],s2[maxn];
struct node
{
    double real, imag;
    node(double real = 0.0, double imag = 0.0)
    {
        this->real = real, this->imag = imag;
    }
    node operator - (const node&elem) const
    {
        return node(this->real - elem.real, this->imag - elem.imag);
    }
    node operator + (const node&elem) const
    {
        return node(this->real + elem.real, this->imag + elem.imag);
    }
    node operator * (const node&elem) const
    {
        return node(this->real * elem.real - this->imag * elem.imag, this->real * elem.imag + this->imag * elem.real);
    }
    void set(double real = 0.0, double imag = 0.0)
    {
        this->real = real, this->imag = imag;
    }
} A[maxn],B[maxn];

void pre()
{
    len1 = strlen(s1),len2 = strlen(s2);
    int maxx = max(len1,len2);
    len = 1;
    while (len < (maxx << 1))
        len <<= 1;
    for (int i = 0; i < len1; i++)
        A[i].set(s1[len1 - i - 1] - '0',0);
    for (int i = 0; i < len2; i++)
        B[i].set(s2[len2 - i - 1] - '0',0);
    for (int i = len1; i < len; i++)
        A[i].set();
    for (int i = len2; i < len; i++)
        B[i].set();
}

void Swap(node &a,node &b)
{
    node temp = a;
    a = b;
    b = temp;
}

void zhuan(node y[])
{
    for (int i = 1, j = len >> 1,k; i < len - 1; i++)
    {
        if (i < j)
            Swap(y[i],y[j]);
        k = len >> 1;
        while (j >= k)
        {
            j -= k;
            k >>= 1;
        }
        if (j < k)
            j += k;
    }
}

void FFT(node y[],int op)
{
    zhuan(y);
    for (int h = 2; h <= len; h <<= 1)
    {
        node temp(cos(op * 2 * pai / h),sin(op * 2 * pai / h));
        for (int i = 0; i < len; i += h)
        {
            node W(1,0);
            for (int j = i; j < i + h / 2; j++)
            {
                node u = y[j];
                node t = W * y[j + h / 2];
                y[j] = u + t;
                y[j + h / 2] = u - t;
                W = W * temp;
            }
        }
    }
    if (op == -1)
        for (int i = 0; i < len; i++)
            y[i].real /= len;
}

void solve(node *A,node *B)
{
    FFT(A,1);
    FFT(B,1);
    for (int i = 0; i < len; i++)
        A[i] = A[i] * B[i];
    FFT(A,-1);
    for (int i = 0; i < len; i++)
        res[i] = (int)(A[i].real + 0.5);
}

void calc(int *a)
{
    for (int i = 0; i < len; i++)
    {
        res[i + 1] += res[i] / 10;
        res[i] %= 10;
    }
    while (--len && res[len] == 0);
}

void print(int *a)
{
    for (int i = len; i >= 0; i--)
        putchar(a[i] + '0');
    printf("\n");
}

int main()
{
    int nn;
    scanf("%d",&nn);
    getchar();
    gets(s1);
    gets(s2);
    pre();
    solve(A,B);
    calc(res);
    print(res);

    return 0;
}

 

posted @ 2018-03-24 14:50  zbtrs  阅读(201)  评论(0编辑  收藏  举报