P3390 【模板】矩阵快速幂
a乘上a的n-1次
#include <bits/stdc++.h>
using namespace std;
int n, mod=1000000007;
long long k;
struct matrix
{
long long a[101][101];
//构造函数,将矩阵初始化为0
matrix(){
memset(a, 0, sizeof(a));
}
//重载 乘法 运算符,b作为第二个参数
matrix operator*(const matrix &b){
matrix result;
for(int i=1; i<=n; ++i){
for(int j=1; j<=n; ++j){
for(int k=1; k<=n; ++k){
result.a[i][j]=(result.a[i][j]+a[i][k]*b.a[k][j])%mod;
}
}
}
return result;
}
}ans, base;
//矩阵快速幂
void quickpow(long long asd)
{
while(asd){
if(asd&1){
ans=ans*base; //用的是重载运算符,不能写成 ans*=base;
}
asd>>=1;
base=base*base;
}
}
int main()
{
scanf("%d %lld", &n, &k);
for(int i=1; i<=n; ++i){
for(int j=1; j<=n; ++j){
scanf("%lld", &base.a[i][j]);
ans.a[i][j]=base.a[i][j];
}
}
// for(int i=1; i<=n; ++i){
// ans.a[i][i]=1;
// }
quickpow(k-1);
for(int i=1; i<=n; ++i){
for(int j=1; j<=n; ++j){
printf("%lld ", ans.a[i][j]);
}
printf("\n");
}
return 0;
}
单位矩阵* a的n次
#include <bits/stdc++.h>
using namespace std;
int n, mod=1000000007;
long long k;
struct matrix
{
long long a[101][101];
//构造函数,将矩阵初始化为0
matrix(){
memset(a, 0, sizeof(a));
}
//重载 乘法 运算符,b作为第二个参数
matrix operator*(const matrix &b){
matrix result;
for(int i=1; i<=n; ++i){
for(int j=1; j<=n; ++j){
for(int k=1; k<=n; ++k){
result.a[i][j]=(result.a[i][j]+a[i][k]*b.a[k][j])%mod;
}
}
}
return result;
}
}ans, base;
//矩阵快速幂
void quickpow(long long asd)
{
while(asd){
if(asd&1){
ans=ans*base; //用的是重载运算符,不能写成 ans*=base;
}
asd>>=1;
base=base*base;
}
}
int main()
{
scanf("%d %lld", &n, &k);
for(int i=1; i<=n; ++i){
for(int j=1; j<=n; ++j){
scanf("%lld", &base.a[i][j]);
// ans.a[i][j]=base.a[i][j];
}
}
//单位矩阵
for(int i=1; i<=n; ++i){
ans.a[i][i]=1;
}
// quickpow(k-1);
quickpow(k);
for(int i=1; i<=n; ++i){
for(int j=1; j<=n; ++j){
printf("%lld ", ans.a[i][j]);
}
printf("\n");
}
return 0;
}
P1962 斐波那契数列 (矩阵快速幂)
矩阵快速幂求斐波那契数列第n项,递推公式
进而转换为矩阵幂次
矩阵快速幂代码
//矩阵快速幂计算 a^n
#include <bits/stdc++.h>
using namespace std;
int mod=1e9+7; //模数
long long n;
struct matrix //定义结构体来表示矩阵
{
long long m[3][3];
};
matrix a, an, fib; //fib是最终斐波那契矩阵, a是矩阵, an为计算完a^n的矩阵
//计算矩阵x(row*column)乘以矩阵y(column*column1),返回值为matrix类型
matrix mul(matrix x, matrix y, int row, int column, int column1)
{
//定义一个新矩阵,来保存乘积,记得初始化
matrix z;
for(int i=0; i<3; ++i){
for(int j=0; j<3; ++j){
z.m[i][j]=0;
}
}
//计算乘积,不断取模
for(int i=1; i<=row; ++i){
for(int j=1; j<=column1; ++j){
for(int k=1; k<=column; ++k){
z.m[i][j]=(z.m[i][j]%mod+(x.m[i][k]%mod)*(y.m[k][j]%mod))%mod;
}
}
}
return z;
}
//矩阵快速幂,计算矩阵asd(row*row)的b次方
matrix quickpow(matrix asd, long long b, int row)
{
//定义并初始化单位矩阵、基数矩阵
matrix ans, base;
for(int i=0; i<3; ++i){
for(int j=0; j<3; ++j){
ans.m[i][j]=0;
base.m[i][j]=a.m[i][j];
}
}
ans.m[1][1]=ans.m[2][2]=1;
//矩阵快速幂,相当于对b进行二进制拆分
while(b){
if(b&1){
//ans=ans*base;
ans=mul(ans, base, 2, 2, 2);
}
b>>=1;
//base*=base;
base=mul(base, base, 2, 2, 2);
}
return ans;
}
int main()
{
scanf("%lld", &n);
if(n<=2){
printf("1");
return 0;
}
//初始化a矩阵
a.m[1][1]=a.m[1][2]=a.m[2][1]=1;
//初始化fib矩阵
fib.m[1][1]=1;
fib.m[2][1]=1;
//计算矩阵a的n-2方
an=quickpow(a, n-2, 2);
//计算最终的斐波那契矩阵
fib=mul(an, fib, 2, 2, 1);
printf("%lld", fib.m[1][1]);
return 0;
}
双倍经验
P1349 广义斐波那契数列
#include <bits/stdc++.h>
using namespace std;
long long p, q, a1, a2, n, m;
long long f[3][2], base[3][3], temp[3][3];
/*
p q fn-1 fn
1 0 fn-2 fn-1
*/
//计算f=base*f矩阵
void mul()
{
for(int i=1; i<=2; ++i){
for(int j=1; j<=1; ++j){
long long sum=0;
for(int k=1; k<=2; ++k){
sum+=(base[i][k]%m)*(f[k][j]%m);
sum%=m;
}
temp[i][j]=sum;
}
}
for(int i=1; i<=2; ++i){
for(int j=1; j<=1; ++j){
f[i][j]=temp[i][j];
}
}
}
//计算base=base*base
void mul2()
{
for(int i=1; i<=2; ++i){
for(int j=1; j<=2; ++j){
long long sum=0;
for(int k=1; k<=2; ++k){
sum+=(base[i][k]%m)*(base[k][j]%m);
sum%=m;
}
temp[i][j]=sum;
}
}
for(int i=1; i<=2; ++i){
for(int j=1; j<=2; ++j){
base[i][j]=temp[i][j];
}
}
}
int main()
{
scanf("%lld %lld %lld %lld %lld %lld", &p, &q, &a1, &a2, &n, &m);
if(n==1){
printf("%lld", a1);
return 0;
}
if(n==2){
printf("%lld", a2);
return 0;
}
f[1][1]=a2;
f[2][1]=a1;
//矩阵乘1次能得到f3, 矩阵乘n-2次能得到fn
base[1][1]=p;
base[1][2]=q;
base[2][1]=1;
n-=2;
while(n){
if(n&1){
//计算f=base*f矩阵
mul();
}
//计算base=base*base
mul2();
n>>=1; //n右移一位
}
printf("%lld", f[1][1]%m);
return 0;
}