[模板] 大数相乘模板
2014-08-14 03:51
274 查看
普通版本
要求不高的时候可以用,时间虽长但代码短。#include<iostream> #include<cstring> #include<cstdio> using namespace std; char n[1000], m[1000]; int re[2000]; int cal(char *n, char *m) { int n_len = strlen(n) - 1; int m_len = strlen(m) - 1; memset(re, 0, sizeof(re)); for (int i = m_len; i >= 0; i--) { for (int j = n_len; j >= 0; j--) { int idx = m_len-i + n_len-j; re[idx] += (n[j]-48) * (m[i]-48); if (re[idx] > 9) { re[idx+1] += re[idx] / 10; re[idx] %= 10; } } } int i = strlen(n) + strlen(m); while (re[i] == 0) i--; return i; } int main() { while (~scanf("%s%s", n, m)) { int i = cal(n, m); while (i >= 0) printf("%d", re[i--]); putchar(10); } return 0; }
快速傅里叶变换版本
#include<iostream> #include<cstdio> #include<cmath> using namespace std; #define MAXN 1000 #define pi acos(-1.0) struct digt { double r; double i; }; digt bitRecv[2*MAXN]; digt va[MAXN*2],vb[2*MAXN]; int ans[MAXN*2]; digt digt_Add(digt a, digt b) { digt t; t.r = a.r+b.r; t.i = a.i+b.i; return t; } digt digt_Sub(digt a, digt b) { digt t; t.r = a.r-b.r; t.i = a.i-b.i; return t; } digt digt_Multi(digt a, digt b) { digt t; t.r = a.r*b.r - a.i*b.i; t.i = a.r*b.i + a.i*b.r; return t; } int rev(int x, int len) //位反置:翻转二进制前len位 { int sum = 0; while (len--) { sum <<= 1; sum |= (x&1); x >>= 1; } return sum; } void bitRevCpy(digt *a,int len) { int bits = 0, t = 1; while (t < len) //计算位长度 { bits++; t <<= 1; } for (int i = 0; i < len; i++) bitRecv[rev(i, bits)] = a[i]; for (int i = 0; i < len; i++) a[i] = bitRecv[i]; } void FFT(digt *Fourier, int len, int on) { int loop, m; digt wm, w; bitRevCpy(Fourier, len); //利用位反置生成输入序列 for (loop = 2; loop <= len; loop <<= 1) { m = loop; //分治后计算长度为m的DFT wm.r = cos(on*2*pi/m); wm.i = sin(on*2*pi/m); //这次单位复根 e^(2*pi/m) 用欧拉公式展开 for (int k = 0; k < len; k += m) //FFT过程 { w.r = 1; w.i = 0; //旋转因子 for (int j = 0; j < m/2; j++) { digt t = digt_Multi(w, Fourier[k+j+m/2]); digt u = Fourier[k+j]; Fourier[k+j] = digt_Add(u, t); Fourier[k+j+m/2] = digt_Sub(u, t); //蝴蝶操作合并 w = digt_Multi(w, wm); //更新旋转因子 } } } if (on == -1) { for (int i = 0; i < len; i++) Fourier[i].r = Fourier[i].r/len; //IDFT } } void conv(digt *a, digt *b, int len) //求卷积 { FFT(a, len, 1); FFT(b, len, 1); for (int i = 0; i < len; i++) a[i] = digt_Multi(a[i], b[i]); FFT(a, len, -1); } int cal(char *n, char *m) // 返回结果的位数 { int i; int n_len = strlen(n); int m_len = strlen(m); int re_len = 1; while (re_len < n_len*2 || re_len < m_len*2 ) re_len <<= 1; for(i = 0; i < re_len; i++) va[i].i = vb[i].i = 0; for (i = 0; n[i]; i++) va[i].r = n[n_len-i-1]-'0'; while (i < re_len) va[i++].r = 0; for (i = 0; m[i]; i++) vb[i].r = m[m_len-i-1]-'0'; while (i < re_len) vb[i++].r = 0; conv(va, vb, re_len); //FFT卷积相当于不进位乘法 for (i = 0; i < re_len; i++) ans[i] = int(va[i].r + 0.5); for (i = 0; i < re_len; i++) { ans[i+1] += ans[i]/10; ans[i] %= 10; } int idx; for (idx = n_len+m_len-1; idx && ans[idx] <= 0; idx--); return idx; } int main() { char n[MAXN*2], m[MAXN*2]; while (~scanf("%s%s", n, m)) { int len = cal(n, m); while(len >= 0) printf("%d", ans[len--]); putchar(10); } return 0; }
相关文章推荐
- 大数相加 大数相乘 模板
- 蓝桥杯PREV-34(数论+大数相乘大数开方模板)
- poj 2389 Bull Math(可做大数相乘模板)
- 大数相乘模板
- 【模板小程序】 十进制大数相乘(正数、负数、0均可),包含合法性检查
- 大数相乘模板
- 大数相乘模板
- 大数相乘(大数阶乘模板)
- 阶乘问题(大数阶乘)简单 n! (一个大数与一个小数相乘的算法 、一个大数与一个小数的除法算法 *【模板】 )
- 模板——大数相乘
- 大数相乘(简单模板)
- 我个人的大数相乘模板
- 大数相乘模板
- 大数相乘算法
- ObjC 实现的大数相加,大数相乘和n的阶乘
- 大数相乘问题
- Linux C/C++ 编程练手 --- 大数相加和大数相乘
- 周教授大数模板【完整版】
- 大数相乘
- C语言 乘法 大数相乘