矩阵快速幂刷题小记
矩阵快速幂模板
传送门: P3390 【模板】矩阵快速幂
Code:
#include<bits/stdc++.h>
using namespace std;
const long long p=1000000007;
inline long long Read(){
long long dx=0,fh=1;
char c=getchar();
while(c>'9'||c<'0'){
if(c=='-') fh=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
dx=dx*10+c-'0';
c=getchar();
}
return dx*fh;
}
long long k,n;
struct Matricx{
long long a[101][101];
}A;
Matricx mul(Matricx x,Matricx y){
Matricx z;
for(long long i=1;i<=n;++i)
for(long long j=1;j<=n;++j){
z.a[i][j]=0;
for(long long u=1;u<=n;++u)
z.a[i][j]=(z.a[i][j]+(x.a[i][u]*y.a[u][j])%p)%p;
}
return z;
}
Matricx quick_pow(Matricx x,long long b){
Matricx r,base=x;
for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) r.a[i][j]=0;
for(int i=1;i<=n;++i) r.a[i][i]=1;
while(b){
if(b&1) r=mul(r,base);
base=mul(base,base);
b>>=1;
}
return r;
}
int main(){
n=Read();k=Read();
for(long long i=1;i<=n;++i)
for(long long j=1;j<=n;++j)
A.a[i][j]=Read();
Matricx B=quick_pow(A,k);
for(long long i=1;i<=n;++i){
for(long long j=1;j<=n;++j)
printf("%lld ",B.a[i][j]);
putchar('\n');
}
return 0;
}
反思与总结:
刚定义的矩阵一定要先全部赋值为0
斐波那契数列
传送门:P1962 斐波那契数列
Code:
#include<bits/stdc++.h>
using namespace std;
const long long p=1000000007;
inline long long Read(){
long long dx=0,fh=1;
char c=getchar();
while(c>'9'||c<'0'){
if(c=='-') fh=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
dx=dx*10+c-'0';
c=getchar();
}
return dx*fh;
}
long long k;
struct Matricx{
long long a[3][3];
}A;
Matricx mul(Matricx x,Matricx y){
Matricx z;
for(long long i=1;i<=2;++i)
for(long long j=1;j<=2;++j){
z.a[i][j]=0;
for(long long u=1;u<=2;++u)
z.a[i][j]=(z.a[i][j]+(x.a[i][u]*y.a[u][j])%p)%p;
}
return z;
}
Matricx quick_pow(Matricx x,long long b){
Matricx r,base=x;
for(int i=1;i<=2;++i) for(int j=1;j<=2;++j) r.a[i][j]=0;
for(int i=1;i<=2;++i) r.a[i][i]=1;
while(b){
if(b&1) r=mul(r,base);
base=mul(base,base);
b>>=1;
}
return r;
}
int main(){
k=Read();
if(k==1||k==2) printf("1");
else{
A.a[1][1]=1,A.a[1][2]=1,A.a[2][1]=1,A.a[2][2]=0;
Matricx B=quick_pow(A,k-2);
printf("%lld",(B.a[1][1]+B.a[1][2])%p);
}
return 0;
}
反思与总结:
- 要特判n=1或n=2的情况
- 记得mod p
广义斐波那契数列
传送门: P1349 广义斐波那契数列
题目分析: 简单推一下:
{
f
[
n
]
=
p
×
f
[
n
−
1
]
+
q
×
f
[
n
−
2
]
f
[
n
−
1
]
=
1
×
f
[
n
−
1
]
+
0
×
f
[
n
−
2
]
⟹
[
f
[
n
]
f
[
n
−
1
]
]
=
[
p
q
1
0
]
∗
[
f
[
n
−
1
]
f
[
n
−
2
]
]
\begin{cases} f[n]=p×f[n-1]+q×f[n-2] \\f[n-1]=1×f[n-1]+0×f[n-2] \end{cases}\implies\begin{bmatrix} f[n] \\ f[n-1] \end{bmatrix} =\begin{bmatrix} p & q \\ 1 & 0 \end{bmatrix}*\begin{bmatrix} f[n-1] \\ f[n-2] \end{bmatrix}
{f[n]=p×f[n−1]+q×f[n−2]f[n−1]=1×f[n−1]+0×f[n−2]⟹[f[n]f[n−1]]=[p1q0]∗[f[n−1]f[n−2]]
最后别忘了
f
[
1
]
=
a
1
f[1]=a1
f[1]=a1,
f
[
2
]
=
a
2
f[2]=a2
f[2]=a2
Code:
#include<bits/stdc++.h>
using namespace std;
inline long long Read(){
long long dx=0,fh=1;
char c=getchar();
while(c>'9'||c<'0'){
if(c=='-') fh=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
dx=dx*10+c-'0';
c=getchar();
}
return dx*fh;
}
long long n,p,a2,a1,q,m;
struct Matricx{
long long a[3][3];
}A;
Matricx mul(Matricx x,Matricx y){
Matricx z;
for(long long i=1;i<=2;++i)
for(long long j=1;j<=2;++j){
z.a[i][j]=0;
for(long long u=1;u<=2;++u)
z.a[i][j]=(z.a[i][j]+(x.a[i][u]*y.a[u][j])%m)%m;
}
return z;
}
Matricx quick_pow(Matricx x,long long b){
Matricx r,base=x;
for(int i=1;i<=2;++i) for(int j=1;j<=2;++j) r.a[i][j]=0;
for(int i=1;i<=2;++i) r.a[i][i]=1;
while(b){
if(b&1) r=mul(r,base);
base=mul(base,base);
b>>=1;
}
return r;
}
int main(){
p=Read();q=Read();a1=Read();a2=Read();n=Read();m=Read();
if(n==1) printf("%lld",a1);
else if(n==2) printf("%lld",a2);
else{
A.a[1][1]=p,A.a[1][2]=q,A.a[2][1]=1,A.a[2][2]=0;
Matricx B=quick_pow(A,n-2);
printf("%lld",((B.a[1][1]*a2)%m+(B.a[1][2]*a1)%m)%m);
}
return 0;
}
【模板】矩阵加速(数列)
传送门:P1939 【模板】矩阵加速(数列)
算法分析:
简单分析一下:
{
f
[
n
]
=
1
×
f
[
n
−
1
]
+
0
×
f
[
n
−
2
]
+
1
×
f
[
n
−
3
]
f
[
n
−
1
]
=
1
×
f
[
n
−
1
]
+
0
×
f
[
n
−
2
]
+
0
×
f
[
n
−
3
]
f
[
n
−
2
]
=
0
×
f
[
n
−
1
]
+
1
×
f
[
n
−
2
]
+
0
×
f
[
n
−
3
]
⟹
[
f
[
n
]
f
[
n
−
1
]
f
[
n
−
2
]
]
=
[
1
0
1
1
0
0
0
1
0
]
∗
[
f
[
n
−
1
]
f
[
n
−
2
]
f
[
n
−
3
]
]
⟹
[
f
[
n
]
f
[
n
−
1
]
f
[
n
−
2
]
]
=
[
1
0
1
1
0
0
0
1
0
]
n
−
3
×
[
f
[
3
]
f
[
2
]
f
[
1
]
]
⟹
[
f
[
n
]
f
[
n
−
1
]
f
[
n
−
2
]
]
=
[
1
0
1
1
0
0
0
1
0
]
n
−
3
×
[
1
1
1
]
\begin{cases} f[n]=1×f[n-1]+0×f[n-2]+1×f[n-3] \\f[n-1]=1×f[n-1]+0×f[n-2]+0×f[n-3] \\f[n-2]=0×f[n-1]+1×f[n-2]+0×f[n-3] \end{cases} \implies \begin{bmatrix} f[n]\\f[n-1]\\f[n-2] \end{bmatrix} =\begin{bmatrix} 1&0&1 \\ 1&0&0 \\0&1&0 \end{bmatrix} *\begin{bmatrix} f[n-1] \\ f[n-2]\\f[n-3] \end{bmatrix} \implies \begin{bmatrix} f[n]\\f[n-1]\\f[n-2] \end{bmatrix} =\begin{bmatrix} 1&0&1 \\ 1&0&0 \\0&1&0 \end{bmatrix}^{n-3}×\begin{bmatrix}f[3]\\f[2]\\f[1] \end{bmatrix}\implies \begin{bmatrix} f[n]\\f[n-1]\\f[n-2] \end{bmatrix} =\begin{bmatrix} 1&0&1 \\ 1&0&0 \\0&1&0 \end{bmatrix}^{n-3}×\begin{bmatrix}1\\1\\1 \end{bmatrix}
⎩⎪⎨⎪⎧f[n]=1×f[n−1]+0×f[n−2]+1×f[n−3]f[n−1]=1×f[n−1]+0×f[n−2]+0×f[n−3]f[n−2]=0×f[n−1]+1×f[n−2]+0×f[n−3]⟹⎣⎡f[n]f[n−1]f[n−2]⎦⎤=⎣⎡110001100⎦⎤∗⎣⎡f[n−1]f[n−2]f[n−3]⎦⎤⟹⎣⎡f[n]f[n−1]f[n−2]⎦⎤=⎣⎡110001100⎦⎤n−3×⎣⎡f[3]f[2]f[1]⎦⎤⟹⎣⎡f[n]f[n−1]f[n−2]⎦⎤=⎣⎡110001100⎦⎤n−3×⎣⎡111⎦⎤
设
[
1
0
1
1
0
0
0
1
0
]
\begin{bmatrix} 1&0&1 \\ 1&0&0 \\0&1&0 \end{bmatrix}
⎣⎡110001100⎦⎤为
A
A
A,则
f
[
n
]
=
A
[
1
]
[
1
]
+
A
[
1
]
[
2
]
+
A
[
1
]
[
3
]
f[n]=A[1][1]+A[1][2]+A[1][3]
f[n]=A[1][1]+A[1][2]+A[1][3]
Code:
#include<bits/stdc++.h>
using namespace std;
const long long p=1000000007;
inline long long Read(){
long long dx=0,fh=1;
char c=getchar();
while(c>'9'||c<'0'){
if(c=='-') fh=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
dx=dx*10+c-'0';
c=getchar();
}
return dx*fh;
}
long long k,T;
struct Matricx{
long long a[4][4];
}A;
Matricx mul(Matricx x,Matricx y){
Matricx z;
for(long long i=1;i<=3;++i)
for(long long j=1;j<=3;++j){
z.a[i][j]=0;
for(long long u=1;u<=3;++u)
z.a[i][j]=(z.a[i][j]+(x.a[i][u]*y.a[u][j])%p)%p;
}
return z;
}
Matricx quick_pow(Matricx x,long long b){
Matricx r,base=x;
for(int i=1;i<=3;++i) for(int j=1;j<=3;++j) r.a[i][j]=0;
for(int i=1;i<=3;++i) r.a[i][i]=1;
while(b){
if(b&1) r=mul(r,base);
base=mul(base,base);
b>>=1;
}
return r;
}
int main(){
A.a[1][1]=1,A.a[1][2]=0,A.a[1][3]=1;
A.a[2][1]=1,A.a[2][2]=0,A.a[2][3]=0;
A.a[3][1]=0,A.a[3][2]=1,A.a[3][3]=0;
T=Read();
for(;T;--T){
k=Read();
if(k==1||k==2||k==3) printf("1\n");
else{
Matricx B=quick_pow(A,k-3);
printf("%lld\n",(B.a[1][1]+B.a[1][2]+B.a[1][3])%p);
}
}
return 0;
}