QUICK-MUL(N,x) if N == 0: return 1.0 y = QUICK-MUL(N / 2 ,x) // 这里是整除,存在向下取整的过程 return N %2 == 0 ? y * y : y * y * x
复杂度分析:
时间复杂度:O(logn),即为递归的层数。
空间复杂度:O(logn),即为递归的层数。这是由于递归的函数调用会使用栈空间。
迭代版本
假设要计算 x9:
形式化来讲:
nxn=2i0+2i1+⋯+2ik=x2i0×x2i1×⋯×x2ik
因此算法可以这样写,把 n 看成一个二进制数,从 n 的低位开始依次检查二进制位,如果为 1,则把当前 x 乘到结果中。每次检查下一位时,x 自身翻一番。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
def quickMul(N): ans = 1.0 # 贡献的初始值为 x x_contribute = x # 在对 N 进行二进制拆分的同时计算答案 while N > 0: if N %2 == 1: # 如果 N 二进制表示的最低位为 1,那么需要计入贡献 ans *= x_contribute # 将贡献不断地平方 x_contribute *= x_contribute # 舍弃 N 二进制表示的最低位,这样我们每次只要判断最低位即可 N //= 2 return ans
publicstaticvoidmain(String[] args)throws Exception { Scannerin=newScanner(System.in); // 输入构造 intn= in.nextInt(); longk= in.nextLong(); long[][] A = newlong[n][n]; for (inti=0; i < n; i++) { for (intj=0; j < n; j++) { A[i][j] = in.nextInt(); } }
// 单位矩阵 long[][] ans = getUnitMatrix(n);
// 快速幂 ans = fast_expo(n, k, A, ans);
// 输出构造 for (inti=0; i < n; i++) { for (intj=0; j < n; j++) { System.out.print(ans[i][j] + " "); } System.out.println(); } }
privatestaticlong[][] fast_expo(int n, long k, long[][] A, long[][] ans) { while (k > 0) { if ((k & 1) == 1) { ans = mult(ans, A, n); } k >>= 1; A = mult(A, A, n); } return ans; }
privatestaticlong[][] getUnitMatrix(int n) { long[][] ans = newlong[n][n]; for (inti=0; i < n; i++) { ans[i][i] = 1L; } return ans; }
publicstaticlong[][] mult(long[][] A, long[][] B, int n) { long[][] ans = newlong[n][n]; for (inti=0; i < n; i++) { for (intj=0; j < n; j++) { for (intk=0; k < n; k++) { ans[i][j] += (A[i][k] * B[k][j]) % MOD; } ans[i][j] %= MOD; } } return ans; } }