矩阵乘法必须满足第一个矩阵的列等于第二个矩阵的行。 结果矩阵的行是第一个矩阵的行,列是第二个矩阵的列。 矩阵乘法行列各元素相乘。 矩阵快速幂利用幂的二分优化。 利用运算符重载进行一系列更方便的操作。
template <typename Type>
long long ipow(Type x, Type n, Type mod){
long long result = 1L L;
while (n) {
if (n & 1 )
result = (result*x) % mod;
x = ((long long )x*x) % mod;
n >>= 1 ;
}
return result;
}
struct mat{
int r = 0 ;
int c = 0 ;
vector <vector <long long > > rect;
mat(int r, int c) : r(r),c(c){
rect.resize(r);
for (int i = 0 ; i < r; ++i)
rect[i].resize(c);
}
mat() = default ;
void in(){
for (int i = 0 ; i < r; ++i)
for (int j = 0 ; j < c; ++j)
scanf ("%I64d" ,&rect[i][j]);
}
void out(){
for (int i = 0 ; i < r; ++i){
for (int j = 0 ; j < c; ++j){
if (j == 0 )
printf ("%I64d" ,rect[i][0 ]);
else
printf (" %I64d" ,rect[i][j]);
}
printf ("\n" );
}
}
void init(){
for (int i = 0 ; i < r; ++i)
for (int j = 0 ; j < c; ++j)
rect[i][j] = (i == j);
}
mat operator * (mat& rhs){
mat ans(r,rhs.c);
long long res;
if (c == rhs.r){
for (int i = 0 ; i < r; ++i){
for (int j = 0 ; j < rhs.c; ++j){
res = 0L L;
for (int k = 0 ; k < c; ++k){
res += rect[i][k] * rhs.rect[k][j];
}
ans.rect[i][j] = res;
}
}
}
return ans;
}
void operator *= (mat& rhs){
mat ans(r,rhs.c);
long long res;
if (c == rhs.r){
for (int i = 0 ; i < r; ++i){
for (int j = 0 ; j < rhs.c; ++j){
res = 0L L;
for (int k = 0 ; k < c; ++k){
res += rect[i][k] * rhs.rect[k][j];
}
ans.rect[i][j] = res;
}
}
}
rect = ans.rect;
}
mat operator ^ (int k){
mat ans(r,c);
ans.init();
for (;k;k >>= 1 ){
if (k & 1 )
ans *= (*this );
(*this ) *= (*this );
}
return ans;
}
void operator ^= (int k){
mat ans(r,c);
ans.init();
for (;k;k >>= 1 ){
if (k & 1 )
ans *= (*this );
(*this ) *= (*this );
}
(*this ) = ans;
}
};