关于快速幂取模
今天看算法书的时候,看到一道关于快速幂取模的题,心想好像不难,便写了一下,发现我的渣渣
代码写的比正常的O(N)复杂度还要慢(天知道我怎么做到的T_T),渣渣代码如下:
1 public static long fastMi(long x,long n){ 2 if(n==1){ 3 return x; 4 } 5 if(n%2==0){ 6 return fastMi(x,n/2)*fastMi(x,n/2); 7 }else{ 8 return fastMi(x,n/2)*fastMi(x,n/2+1); 9 } 10 }
于是只好从最基本的复杂度O(N)的算法来看我哪错了
当计算x的n次方余m的值时,正常做法一般是复杂度O(N)的做法,如下:
1 /** 2 * @param x 3 * @param n 4 * @param m 5 * @return 返回x^n%m的值 6 */ 7 public long power(long x,long n,long m){ 8 long result = 1; 9 for(int i=1;i<=n;i++){ 10 result = result * x % m; 11 } 12 return result; 13 }
这种做法就是单纯的基于x的平方等于x*x这种感觉,
不过,如果用上快速幂,那时间复杂度会缩小的log级别,而快速幂
就是基于下面这个观测结果得出的:
n为偶数时:
x^n = x^(n/2)*x^(n/2)
n为奇数时:
x^n = x * x^(n-1) = x * x^(n-1/2)*x^(n-1/2)
代码如下:
1 public long power(long x,long n,long m){ 2 if(n==0){ 3 return 1; 4 } 5 result = power(x,n/2,m); 6 if(n%2==0){ 7 return result*result; 8 }else{ 9 return result*result*x; 10 } 11 }
于是发现我原本的做法又多了几道递归的分支路线,而原本是根本不需要那些分支路线的,只需要一次赋值等于就好了= =