大數相乘以及其高效演算法
阿新 • • 發佈:2019-02-16
測試用例:
999 999
998001
999999999999 999999999999
999999999998000000000001
下面分析下999*999
6 5 4
6 5 4
36 30 24
30 25 20
24 20 16
-------------------------------
這裡結果 就清楚了
但是要注意 asc 碼 最大是 128 所以要在加的時候就處理好
下面給出程式碼 普通 最一般的程式碼
/* Name: hondely Copyright: hondely Author: hondely Date: 05/11/11 14:34 Description: */ #include <iostream> using namespace std; void mul(char *ch1, char *ch2) { int len1=strlen(ch1),len2=strlen(ch2); char ch3[1000009]; int i,j,carry; for (i=0; i<1000009; i++) ch3[i]='\0';//=0 for (i=0; i<len1; i++) { for (j=0; j<len2; j++)//下面可能asc碼大於128 { ch3[i+j]=ch3[i+j]+(ch1[i]-'0')*(ch2[j]-'0');//這裡用字元型表示ch3要注意 if (ch3[i+j]>9&&(i+j)>0) { ch3[i+j-1]+=ch3[i+j]/10; ch3[i+j]=ch3[i+j]%10; } } } for (i=len1+len2-1; i>0; --i)//防止上面進位時大於9的情況 { if (ch3[i]>9) { ch3[i-1]=ch3[i-1]+ch3[i]/10; ch3[i]%=10; } } if (ch3[0]>9)//if (ch[3]>99) { cout<<ch3[0]/10; ch3[0]=ch3[0]%10; } for (i=0; i<len1+len2-1; i++) cout<<char(ch3[i]+48); cout<<endl; } int main() { char ch1[10005],ch2[10005]; cout<<"please input: "; while (cin>>ch1>>ch2) { mul(ch1,ch2); } return 0; }
下面是傅立葉高效演算法,自己不懂順便貼上過來了 對傅立葉變換一竅不通
#include <iostream> #include <cmath> #include <complex> #include <cstring> using namespace std; const double PI = acos(-1); typedef complex<double> cp; typedef long long int64; const int N = 1 << 16; int64 a[N], b[N], c[N << 1]; void bit_reverse_copy(cp a[], int n, cp b[]) { int i, j, k, u, m; for (u = 1, m = 0; u < n; u <<= 1, ++m); for (i = 0; i < n; ++i) { j = i; k = 0; for (u = 0; u < m; ++u, j >>= 1) k = (k << 1) | (j & 1); b[k] = a[i]; } } void FFT(cp _x[], int n, bool flag) { static cp x[N << 1]; bit_reverse_copy(_x, n, x); int i, j, k, kk, p, m; for (i = 1, m = 0; i < n; i <<= 1, ++m); double alpha = 2 * PI; if (flag) alpha = -alpha; for (i = 0, k = 2; i < m; ++i, k <<= 1) { cp wn = cp(cos(alpha / k), sin(alpha / k)); for (j = 0; j < n; j += k) { cp w = 1, u, t; kk = k >> 1; for (p = 0; p < kk; ++p) { t = w * x[j + p + kk]; u = x[j + p]; x[j + p] = u + t; x[j + p + kk] = u - t; w *= wn; } } } memcpy(_x, x, sizeof(cp) * n); } void polynomial_multiply(int64 a[], int na, int64 b[], int nb, int64 c[], int &nc) { int i, n; i = max(na, nb) << 1; for (n = 1; n < i; n <<= 1); static cp x[N << 1], y[N << 1]; for (i = 0; i < na; ++i) x[i] = a[i]; for (; i < n; ++i) x[i] = 0; FFT(x, n, 0); for (i = 0; i < nb; ++i) y[i] = b[i]; for (; i < n; ++i) y[i] = 0; FFT(y, n, 0); for (i = 0; i < n; ++i) x[i] *= y[i]; FFT(x, n, 1); for (i = 0; i < n; ++i) { c[i] =(int64)(x[i].real() / n + 0.5); } for (nc = na + nb - 1; nc > 1 && !c[nc - 1]; --nc); } const int LEN = 5, MOD = 100000; void convert(char *s, int64 a[], int &n) { int len = strlen(s), i, j, k; for (n = 0, i = len - LEN; i >= 0; i -= LEN) { for (j = k = 0; j < LEN; ++j) k = k * 10 + (s[i + j] - '0'); a[n++] = k; } i += LEN; if (i) { for (j = k = 0; j < i; ++j) k = k * 10 + (s[j] - '0'); a[n++] = k; } } void print(int64 a[], int n) { printf("%I64d", a[--n]); while (n) printf("%05I64d", a[--n]); puts(""); } char buf[N + 10]; int main() { int na, nb, nc; while (scanf("%s", buf) != EOF) { bool sign = false; if (buf[0] == '-') { sign = !sign; convert(buf + 1, a, na); } else convert(buf, a, na); scanf("%s", buf); if (buf[0] == '-') { sign = !sign; convert(buf + 1, b, nb); } else convert(buf, b, nb); polynomial_multiply(a, na, b, nb, c, nc); int64 t1, t2; t1 = 0; for (int i = 0; i < nc; ++i) { t2 = t1 + c[i]; c[i] = t2 % MOD; t1 = t2 / MOD; } for (; t1; t1 /= MOD) c[nc++] = t1 % MOD; if (sign) putchar('-'); print(c, nc); } return 0; }