题目描述
给出两个n位10进制整数x和y,你需要计算x*y。
输入输出格式
输入格式:
第一行一个正整数n。 第二行描述一个位数为n的正整数x。 第三行描述一个位数为n的正整数y。
输出格式:
输出一行,即x*y的结果。(注意判断前导0)
输入输出样例
说明
数据范围:
n<=60000
来源:bzoj2179
本题数据为洛谷自造数据,使用CYaRon耗时5分钟完成数据制作。
寻找了很久,最终还是发现算法导论的FFT讲解的是最详细的,前置技能:复数四则运算,矩阵基本运算。推荐这一篇博客:点击-> “这一篇博客”这样我们可以把一个数看成一个多项式(a1 * 10 ^ 0 + a2 * 10 ^ 1 + a3 * 10 ^ 2........)进行快速傅里叶变换,代码如下:
#include<cstdio> #include<cstring> #include<algorithm> #include<complex> #include<cmath> #define Pi acos(-1) using namespace std; const int maxn = 2e6 + 5; typedef complex<double> E; E a[maxn << 1], b[maxn << 1]; int R[maxn << 1], ans[maxn << 1]; char s1[maxn], s2[maxn]; int n, m, x, l; int FFT(E * a, int type) { /*按逆序归位*/ for(register int i = 0; i < n; ++i) if(i < R[i]) swap(a[i], a[R[i]]); for(register int i = 1; i < n; i <<= 1) { E Wn(cos(Pi / i), sin(Pi * type / i)); for(register int p = i << 1, j = 0; j < n; j += p) { E w(1, 0); for(register int k = 0; k < i; ++k, w *= Wn) { E x = a[j + k]; E y = w * a[j + k + i]; a[j + k] = x + y, a[j + k + i] = x - y; } } } } int main() { scanf("%d", &n); scanf("%s%s", s1, s2); n = strlen(s1), m = strlen(s2); for(register int i = --n; i >= 0; --i) a[n - i] = s1[i] - '0'; for(register int i = --m; i >= 0; --i) b[m - i] = s2[i] - '0'; m = n + m; for(n = 1; n <= m; n <<= 1) ++l; /*蝴蝶操作通过i >> 1的逆序递推i的逆序*/ for(register int i = 0; i < n; ++i) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (l - 1)); FFT(a, 1), FFT(b, 1); for(register int i = 0; i <= n; ++i) a[i] = a[i] * b[i]; FFT(a, -1); for(register int i = 0; i < n; ++i) ans[i] = int(a[i].real() / n + 0.5); for(register int i = 0; i < n; ++i) ans[i + 1] += ans[i] / 10, ans[i] = ans[i] % 10; int p = n; for(; p >= 0 && !ans[p]; --p); if(p == -1) { printf("0"); return 0; } for(register int i = p; i >= 0; --i) printf("%d", ans[i]); return 0; }
没有帐号? 立即注册