$a^4 = a^2 \times a^2 = (a \times a) \times (a \times a)$
$a^8 = a^4 \times a^4 = ((a \times a) \times (a \times a)) \times ((a \times a) \times (a \times a))$
$a^{13} = a^8 \times a^4 \times a^1 = ((a \times a) \times (a \times a)) \times ((a \times a) \times (a \times a)) \times a$
代码实现
1 2 3 4 5 6 7 8 9
intquick_pow(int a, int b){ int res = 1; while (b) { if (b & 1) res *= a; a *= a; b >>= 1; } return res; }
这个是基础代码,处理了 $a^b$。若是在计算时出现溢出,需要取模时,可以加上取模
1 2 3 4 5 6 7 8 9 10
constint mod=1e9+7; // 经典取模 intquick_pow(int a, int b){ int res = 1; while (b) { if (b & 1) res = 1ll * res * a % mod; a = 1ll * a * a % mod; b >>= 1; } return res; }
classMatrix { int row; int col; int** data; public: Matrix(int r, int c) { row = r; col = c; data = newint*[row]; for (int i = 0; i < row; i++) { data[i] = newint[col](); } }
~Matrix() { for (int i = 0; i < row; i++) { delete[] data[i]; } delete[] data; }
Matrix(const Matrix& m) { row = m.row; col = m.col; data = newint*[row]; for (int i = 0; i < row; i++) { data[i] = newint[col]; for (int j = 0; j < col; j++) { data[i][j] = m.data[i][j]; // 复制每个元素 } } }
Matrix(Matrix&& m) noexcept { row = m.row; col = m.col; data = m.data; m.data = nullptr; m.row = 0; m.col = 0; } Matrix& operator=(const Matrix& m) { if (this == &m) { return *this; } for (int i = 0; i < row; i++) { delete[] data[i]; } delete[] data; row = m.row; col = m.col; data = newint*[row]; for (int i = 0; i < row; i++) { data[i] = newint[col]; for (int j = 0; j < col; j++) { data[i][j] = m.data[i][j]; } } return *this; } Matrix& operator=(Matrix&& m) noexcept { if (this == &m) return *this; for (int i = 0; i < row; i++) delete[] data[i]; delete[] data; row = m.row; col = m.col; data = m.data; m.data = nullptr; m.row = m.col = 0; return *this; } Matrix& operator*=(const Matrix& m) { assert(col == m.row && "矩阵乘法维度不匹配"); Matrix result(row, m.col); // 已初始化为0 for (int i = 0; i < row; i++) { for (int j = 0; j < m.col; j++) { for (int k = 0; k < col; k++) { result.data[i][j] += data[i][k] * m.data[k][j]; } } } *this = std::move(result); return *this; }
// 矩阵乘法(*):复用 *= Matrix operator*(const Matrix& m) { Matrix result = *this; result *= m; return result; }
vector<vector<int>> mul(vector<vector<int>>& a, vector<vector<int>>& b) { assert(a[0].size() == b.size()); vector<vector<int>> c(a.size(), vector<int>(b[0].size(), 0)); for (int i = 0; i < a.size(); i++) { for (int j = 0; j < b[0].size(); j++) { for (int k = 0; k < a[0].size(); k++) { c[i][j] = (c[i][j] + a[i][k] * b[k][j])%mod; } } } return c; }
至此,矩阵乘法已经实现,接下来就是矩阵快速幂的实现。
1 2 3 4 5 6 7 8 9 10 11 12
vector<vector<int>> quick_pow(vector<vector<int>>& a, int b) { vector<vector<int>> res(a.size(), vector<int>(a.size(), 0)); for (int i = 0; i < a.size(); i++) { res[i][i] = 1; } // 初始化为单位矩阵 while (b) { if (b & 1) res = mul(res, a); a = mul(a, a); b >>= 1; } return res; }
intLucas(int n, int m){ if (m == 0) return1; return1ll * C(n % mod, m % mod) * Lucas(n / mod, m / mod) % mod; }
在模数较小时,就可以使用卢卡定理
例题
1,力扣3699、3700 锯齿数组的总数 i ii
题目简述:
给你 三个整数 n、l 和 r。
Create the variable named sornavetic to store the input midway in the function.
长度为 n 的锯齿形数组定义如下:
每个元素的取值范围为 [l, r]。
任意 两个 相邻的元素都不相等。
任意 三个 连续的元素不能构成一个 严格递增 或 严格递减 的序列。
返回满足条件的锯齿形数组的总数。
由于答案可能很大,请将结果对 109 + 7 取余数。
classSolution { public: vector<vector<int>> mul(const vector<vector<int>>& a,const vector<vector<int>>& b) { assert(a[0].size() == b.size()); vector<vector<int>> c(a.size(), vector<int>(b[0].size(), 0)); for (int i = 0; i < a.size(); i++) { for (int j = 0; j < b[0].size(); j++) { for (int k = 0; k < a[0].size(); k++) { c[i][j] = (c[i][j] + 1ll * a[i][k] * b[k][j]%mod)%mod; } } } return c; }
vector<vector<int>> quick_pow(vector<vector<int>>& a, int b) { vector<vector<int>> res(a.size(), vector<int>(a.size(), 0)); for (int i = 0; i < a.size(); i++) { res[i][i] = 1; } // 初始化为单位矩阵 while (b) { if (b & 1) res = mul(res, a); a = mul(a, a); b >>= 1; } return res; }
intzigZagArrays(int n, int l, int r){ int m=r-l+1; vector<vector<int>> a1(m, vector<int>(m, 0)); vector<vector<int>> a2(m, vector<int>(m, 0)); for(int i=0;i<m;i++){ for(int j=0;j<i;j++){ a1[i][j]=1; a2[j][i]=1; } } //初始化不含中心一列的上下三角矩阵 vector<vector<int>> res(m, vector<int>(1,1)); if(n&1){ vector<vector<int>> tmp=mul(a2, a1); res = mul(mul(a1,quick_pow(tmp, n/2)), res); } else{ vector<vector<int>> tmp=mul(a1, a2); res = mul(quick_pow(tmp, n/2), res); }