对于计算 xy 只需要计算 x2y×x2y ,如果 y 是奇数只需要再乘 x ,这样就可以把 O(n) 的时间复杂度降为 O(logn) 。
递归版:
1 2 3 4 5 6 7 8
intfastPower(int x, int y, int p){ if(y == 0) return1; int z = fastPower(x, y >> 1, p); z = 1ll * z * z % p; if(y % 2 == 1) z = 1ll * z * x % p; return z; }
迭代版:
1 2 3 4 5 6 7 8 9 10 11
intfastPower(int x,int y,int p) { int ans = 1; while(y) { if(y & 1) ans = 1ll * ans * x % p; x = 1ll * x * x % p; y >>= 1; } return ans; }
矩阵乘法
条件:第一个矩阵的列数等于第二个矩阵的行数。
得到的矩阵的行数等于第一个矩阵的行数,列数等于第二个矩阵的列数。
计算得到的矩阵第 i 行第 j 列的方法为取出第一个矩阵的第 i 行与第二个矩阵的第 j 列对应位置相乘再求和。
这里通过重载运算符简化计算。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
structMatrix { int n, m; int z[110][110]; Matrix() { n = m = 0; memset(z, 0, sizeof(z)); } };
Matrix operator* (const Matrix& a, const Matrix& b) { Matrix c; c.n = a.n; c.m = b.m; for(int i = 1; i <= c.n; i++) for(int j = 1; j <= c.m; j++) for(int k = 1; k <= a.m; k++) c.z[i][j] = c.z[i][j] + a.z[i][k] * b.z[k][j]; return c; }
矩阵快速幂
以计算斐波那契数列为例,通过递推式求第 n 个数的时间复杂度显然是 o(n) 的,如果构造一个矩阵 M 使得 [fifi−1] 与 M 相乘能得到 [fi+1fi] ,则 fn=f1×Mn−1,通过矩阵乘法的法则可以得到矩阵 M 。
[fi+1fi]=[fifi−1][1110]
所以可以通过矩阵的快速幂来优化递推。
由于已经重载了矩阵的乘号,所以只需要更改部分代码即可。
递归版:
1 2 3 4 5 6 7 8 9 10 11 12
Matrix fastPower(Matrix x, int y){ if(y == 0) { Matrix z; z.n = z.m = x.n; for(int i = 1; i <= z.n; i++) z.z[i][i] = 1; return z; } Matrix z = fastPower(x, y >> 1); z = z * z; if(y % 2 == 1) z = z * x; return z; }
迭代版:
1 2 3 4 5 6 7 8 9 10 11
Matrix fastPower(Matrix x, longlong y){ Matrix ans; ans.n = ans.m = x.n; for(int i = 1; i <= x.n; i++) ans.z[i][i] = 1; while(y) { if(y & 1) ans = ans * x; x = x * x; y >>= 1; } return ans; }