快速幂模板(仅作记录)
普通n次幂
using type_c = int; //类型为int;
using ll = long long;
#define mod 1000000000
type_c my_pow(type_c a, ll n){
if(n == 0) return 1;
if(n % 2 == 0)
return my_pow(a, n/2) * my_pow(a, n/2) % mod;
else
return a * my_pow(a, n-1) % mod;
}
显然,在递归的时候进行了大量重复不必要的计算(a^(n/2)算了两次),考虑设置一个临时变量 t 记录 my_pow(a, n/2) 。
递归快速幂
using type_c = int; //类型为int;
using ll = long long;
#define mod 1000000000
type_c my_pow(type_c a, ll n){
if(n == 0) return 1;
if(n % 2 == 0){
type_c t = my_pow(a, n/2);
return t * t % mod; //小心t*t溢出
}
else
return a * my_pow(a, n-1) % mod;
}
时间复杂度为O(logn)。
非递归快速幂
在求 a n a^{n} an时候,我们可以把n写成二进制的形式,即将n拆成了 2 i 2^{i} 2i + 2 j 2^{j} 2j + 2 k 2^{k} 2k …的形式,这个时候 a n a^{n} an = a^( 2 i 2^{i} 2i + 2 j 2^{j} 2j + 2 k 2^{k} 2k … )= a 2 i a^{2^i} a2i * a 2 j a^{2^j} a2j * a 2 k a^{2^k} a2k…。i, j, k,…为二进制位为1的位次(从0开始)。
using type_c = int; //类型为int;
using ll = long long;
#define mod 1000000000
type_c my_pow(type_c a, ll n){
type_c ans = 1;
while(n){
if(n & 1) //如果n的当前末位为1,说明到了拆分的项之一的位置(文中的i, j, k.......),需要进行一次计算
ans = ans * a % mod; //ans乘上当前的a^(2^i)
a = a * a % mod; //a自乘,求得当前的a^(2^i), i为上文中的i, j, k........
n >>= 1; //n往右移一位
}
return ans;
}
矩阵快速幂
写出矩阵运算,然后把矩阵作为参数传入快速幂模板即可。
#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
const int maxm = 105;//矩阵最大维数
using type_c = long long; //类型为long long;
int m;
struct Matrix {
type_c a[maxm][maxm];
Matrix() { memset(a, 0, sizeof a); }
Matrix operator*(const Matrix &b) const {//重载矩阵乘法
Matrix t;
for (int i = 0; i < m; ++i)
for (int j = 0; j < m; ++j)
for (int k = 0; k < m; ++k)
t.a[i][j] = (t.a[i][j] + a[i][k] * b.a[k][j]) % mod;
return t;
}
void init(){
memset(a, 0, sizeof(a));
for(int i = 0; i < m; i++)
a[i][i] = 1;
}
void output(){
for(int i = 0; i < m; i++){
for(int j = 0; j < m; j++){
cout << a[i][j];
if(j != m-1)
cout << ' ';
}
cout << endl;
}
}
void input(){
for(int i = 0; i < m; i++)
for(int j = 0; j < m; j++)
cin >> a[i][j];
}
};
Matrix my_pow(Matrix base, type_c n){
Matrix ans;
ans.init();
while(n){
if(n & 1) //如果n的当前末位为1
ans = ans * base; //ans乘上当前的a
base = base * base; //a自乘
n >>= 1; //n往右移一位
}
return ans;
}
int main(){
type_c n;
cin >> m >> n;
Matrix base;
base.input();
my_pow(base, n).output();
return 0;
}