[BZOJ 2179] FFT快速傅立叶
2179: FFT快速傅立叶
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 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
3
4
Sample Output
12
数据范围:
n<=60000
数据范围:
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; }