P1919 FFT加速高精度乘法
传送门:https://www.luogu.org/problemnew/show/P1919
题意:
给出两个n位10进制整数x和y,你需要计算x*y。
题解:
对于十进制数我们可以将其转换成
(a0*10^0+a1*10^1+a2*10^2...an*10^n)
那么对于两个数,我们就可以求出两个的系数表示后得到a的点乘式和b的点乘式
最后得到的答案就是a和b的多项式的系数,这个问题O(n)扫一遍,
处理一下输出即可
代码:
#include <set>
#include <map>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********
")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]
"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]
"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]
"
const int maxn = 1e6 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double Pi = acos(-1.0);
LL quick_pow(LL x, LL y) {
LL ans = 1;
while(y) {
if(y & 1) {
ans = ans * x % mod;
} x = x * x % mod;
y >>= 1;
} return ans;
}
struct complex {
double x, y;
complex(double xx = 0, double yy = 0) {
x = xx, y = yy;
}
} a[maxn], b[maxn];
complex operator + (complex a, complex b) {
return complex(a.x + b.x, a.y + b.y);
}
complex operator - (complex a, complex b) {
return complex(a.x - b.x, a.y - b.y);
}
complex operator * (complex a, complex b) {
return complex(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);
}
int n, m;
int l, r[maxn];
int limit = 1;
void fft(complex *A, int type) {
for(int i = 0; i < limit; i++) {
if(i < r[i]) swap(A[i], A[r[i]]);
}
for(int mid = 1; mid < limit; mid <<= 1) {
complex Wn(cos(Pi / mid), type * sin(Pi / mid));
for(int R = mid << 1, j = 0; j < limit; j += R) {
complex w(1, 0);
for(int k = 0; k < mid; k++, w = w * Wn) {
complex x = A[j + k], y = w * A[j + mid + k];
A[j + k] = x + y;
A[j + k + mid] = x - y;
}
}
}
}
int ans[maxn];
char numA[maxn], numB[maxn];
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
int n;
while(scanf("%d", &n) != EOF) {
scanf("%s %s", numA, numB);
// debug3(n,numA,numB);
int lena = 0;
int lenb = 0;
for(int i = n - 1; i >= 0; i--) {
a[lena++].x = numA[i] - '0';
}
for(int i = n - 1; i >= 0; i--) {
b[lenb++].x = numB[i] - '0';
}
while(limit < n + n) limit <<= 1, l++;
for(int i = 0; i <= limit; i++) {
r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
}
fft(a, 1);
fft(b, 1);
for(int i = 0; i <= limit; i++) {
a[i] = a[i] * b[i];
}
fft(a, -1);
int tot = 0;
for(int i = 0; i <= limit; i++) {
ans[i] += (int)(a[i].x / limit + 0.5);
if(ans[i] >= 10) {
ans[i + 1] += ans[i] / 10;
ans[i] %= 10;
limit += (i == limit);
}
}
while(!ans[limit] && limit >= 1) limit--;
limit++;
while(--limit >= 0) cout << ans[limit];
}
return 0;
}