[BZOJ 2179] FFT快速傅立叶

杀马特。学长 韩版系。学妹 提交于 2019-12-02 17:06:15

2179: FFT快速傅立叶

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 4621  Solved: 2498
[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
 
法法塔模板
本来在纠结背不住板子
突然想起来ACM是可以带板子进场的
嗨森
#include <bits/stdc++.h>
using namespace std;
const int maxn = 262144;
struct comp{
    double x, y;
    comp(double _x = 0, double _y = 0){
        x = _x;
        y = _y;
    }
    friend comp operator * (const comp &a, const comp &b){
        return comp(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);
    }
    friend comp operator + (const comp &a, const comp &b){
        return comp(a.x + b.x, a.y + b.y);
    }
    friend comp operator - (const comp &a, const comp &b){
        return comp(a.x - b.x, a.y - b.y);
    }
}f[maxn], g[maxn];
int rev[maxn];
void dft(comp A[], int len, int kind){
    for(int i = 0; i < len; i++){
        if(i < rev[i]){
            swap(A[i], A[rev[i]]);
        }
    }
    for(int i = 1; i < len; i <<= 1){
        comp wn(cos(acos(-1.0) / i), kind * sin(acos(-1.0) / i));
        for(int j = 0; j < len; j += (i << 1)){
            comp tmp(1, 0);
            for(int k = 0; k < i; k++){
                comp s = A[j + k], t = tmp * A[i + j + k];
                A[j + k] = s + t;
                A[i + j + k] = s - t;
                tmp = tmp * wn;
            }
        }
    }
    if(kind == -1) for(int i = 0; i < len; i++) A[i].x /= len;
}
char a[600000 + 10];
int ans[maxn] = {0};
int main(){
    int n, len, L = 0;
    scanf("%d", &n);
    for(len = 1; len < n + n - 1; len <<= 1, L++);
    scanf("%s", a);
    for(int i = 0; i < n; i++) f[i].x = a[n - i - 1] ^ 48;
    scanf("%s", a);
    for(int i = 0; i < n; i++) g[i].x = a[n - i - 1] ^ 48;
    for(int i = 0; i < len; i++){
        rev[i] = rev[i >> 1] >> 1 | (i & 1) << L - 1;
    }
    dft(f, len, 1); dft(g, len, 1);
    for(int i = 0; i < len; i++) f[i] = f[i] * g[i];
    dft(f, len, -1);
    for(int i = 0; i < len; i++)
        ans[i] = (int)(f[i].x + 0.5);
    for(int i = 0; i < len; i++){
        if(ans[i] > 9){
            ans[i + 1] += ans[i] / 10;
            ans[i] %= 10;
        }
    }
    while(!ans[len - 1]) len--;
    for(int i = len - 1; ~i; i--) printf("%d", ans[i]);
    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!