俄国农民指数算法
1 2 3 4 5 6 7 8 9 10 11 12
| long long FastPow(long long g,long long e,const long long m) { long long ans=1; while(e) { if(e&1) ans=(ans*g)%m; g=(g*g)%m; e>>=1; } return ans; }
|
1 2 3 4 5 6 7 8 9 10 11 12
| long long FastPow(long long g,long long e,const long long m) { long long ans=1; while(e) { ans=(ans*ans)%m; if(e&1) ans=(ans*g)%m; e>>=1; } return ans; }
|
原理:
相同点
两种算法都需要平均1.5∗(n −1) 次乘法。
不同点
第二种是用固定的g值作乘法,第一种的g值是变化的,因此在硬件实现时,需要增加一个寄存器。
第一种算法中,平方和模乘是独立的,可以并行运算。但在第二种算法中不能。
俄国农民乘法算法
图片见下:
1 2 3 4 5 6 7 8 9 10 11
| int f(int a,int b){ int ans=b&(a%2); while(a!=0){ b=b*2; if(a%2==0){ ans+=b; } a=a/2; } return ans; }
|
笔纸算法
简单来说,就是用程序模拟手算乘法时的竖式计算。
1 2 3 4 5 6 7 8 9 10 11 12 13
| void mul(int a[], int b[], int c[]) { clear(c); for (int i = 0; i < LEN - 1; ++i) { for (int j = 0; j <= i; ++j) c[i] += a[j] * b[i - j]; if (c[i] >= 10) { c[i + 1] += c[i] / 10; c[i] %= 10; } } }
|
比笔纸算法更快的算法
用递归的方式优化乘法。
1 2 3 4 5 6 7 8 9 10 11
| multiply(u, v) Input: 正整数 u、 v, in binary Output: uv n = max(size of u, size of v) if n = 1 return xy U1=u的高n/2位, U0 = u的低 n/2 位 V1 =v的高n/2位, V0= v的低 n/2 位 P1 = multiply(U1, V1) P2 = multiply(U0 , V0) P3 = multiply(U1-U0, V0-V1) return =(2^n+2^n/2)P1+2^n/2*P2+(2^n/2+1)P3
|
递归表达式:
最终,算法复杂度约为n的1.5次方。
复数乘法
两个复数相乘时,减少乘法的次数为3次。
1 2 3 4 5
| 复数乘法(a+bi)*(c+di): A=a*d B=b*c C=(a+b)*(c-d) (a+bi)*(c+di)=(C-A+B)+(A+B)i
|