矩阵快速幂,作为学习矩阵优化的前置知识
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=105,MOD=1e9+7;
int n,k;
struct number{int num[N][N];}base,ans;
inline number mul(number a,number b)
{
number c;
for (register int i=1; i<=n; ++i)
for (register int j=1; j<=n; ++j) c.num[i][j]=0;
for (register int i=1; i<=n; ++i)
for (register int j=1; j<=n; ++j)
for (register int k=1; k<=n; ++k)
c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j]%MOD)%MOD;
return c;
}
inline void pow(int k)
{
while (k)
{
if (k&1ll) ans=mul(ans,base);
base=mul(base,base);
k>>=1ll;
}
}
signed main(){
scanf("%lld%lld",&n,&k);
for (register int i=1; i<=n; ++i)
for (register int j=1; j<=n; ++j) scanf("%lld",&base.num[i][j]);
for (register int i=1; i<=n; ++i) ans.num[i][i]=1;
pow(k);
for (register int i=1; i<=n; ++i)
{
for (register int j=1; j<=n; ++j) printf("%lld ",ans.num[i][j]);
puts("");
}
return 0;
}
最基础的矩阵优化题
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MOD=1e9+7;
int n;
struct number{int num[5][5];}base,ans,b;
inline number mul(number a,number b)
{
number c;
for (register int i=1; i<=2; ++i)
for (register int j=1; j<=2; ++j) c.num[i][j]=0;
for (register int i=1; i<=2; ++i)
for (register int j=1; j<=2; ++j)
for (register int k=1; k<=2; ++k)
c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j]%MOD)%MOD;
return c;
}
inline void pow(int k)
{
while (k)
{
if (k&1ll) ans=mul(ans,base);
base=mul(base,base);
k>>=1ll;
}
}
signed main(){
scanf("%lld",&n);
if (n<2)
{
puts("1");
return 0;
}
base.num[1][1]=base.num[1][2]=base.num[2][1]=1;
for (register int i=1; i<=2; ++i) ans.num[i][i]=1;
pow(n-2);
b.num[1][1]=b.num[2][1]=1;
ans=mul(ans,b);
printf("%lld\n",ans.num[1][1]);
return 0;
}
通过打表发现 gcd(f[n],f[m])=f[gcd(n,m)] ,然后就是上一题了
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,m;
const int MOD=1e8;
int gcd(int a,int b)
{
if (a%b==0) return b;
return gcd(b,a%b);
}
struct number{int num[5][5];}base,ans,b;
inline number mul(number a,number b)
{
number c;
for (register int i=1; i<=2; ++i)
for (register int j=1; j<=2; ++j) c.num[i][j]=0;
for (register int i=1; i<=2; ++i)
for (register int j=1; j<=2; ++j)
for (register int k=1; k<=2; ++k)
c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j]%MOD)%MOD;
return c;
}
inline void pow(int k)
{
while (k)
{
if (k&1ll) ans=mul(ans,base);
base=mul(base,base);
k>>=1ll;
}
}
signed main(){
scanf("%lld%lld",&n,&m);
n=gcd(n,m);
if (n<2)
{
puts("1");
return 0;
}
base.num[1][1]=base.num[1][2]=base.num[2][1]=1;
for (register int i=1; i<=2; ++i) ans.num[i][i]=1;
pow(n-2);
b.num[1][1]=b.num[2][1]=1;
ans=mul(ans,b);
printf("%lld\n",ans.num[1][1]);
return 0;
}
改变一下公式就可以了
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MOD=1e9+7;
int T,n;
struct number{int num[5][5];}base,ans,b;
inline number mul(number a,number b)
{
number c;
for (register int i=1; i<=3; ++i)
for (register int j=1; j<=3; ++j) c.num[i][j]=0;
for (register int i=1; i<=3; ++i)
for (register int j=1; j<=3; ++j)
for (register int k=1; k<=3; ++k)
c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j]%MOD)%MOD;
return c;
}
inline void pow(int k)
{
while (k)
{
if (k&1ll) ans=mul(ans,base);
base=mul(base,base);
k>>=1ll;
}
}
signed main(){
scanf("%lld",&T);
while (T--)
{
memset(base.num,0,sizeof(base.num));
memset(ans.num,0,sizeof(ans.num));
memset(b.num,0,sizeof(b.num));
scanf("%lld",&n);
if (n<3)
{
puts("1");
continue;
}
base.num[1][1]=base.num[1][3]=base.num[2][1]=base.num[3][2]=1;
for (register int i=1; i<=3; ++i) ans.num[i][i]=1;
pow(n-3);
b.num[1][1]=b.num[2][1]=b.num[3][1]=1;
ans=mul(ans,b);
printf("%lld\n",ans.num[1][1]);
}
return 0;
}
把初始矩阵改变一下即可
#include <bits/stdc++.h>
#define int long long
using namespace std;
int p,q,a1,a2,n,MOD;
struct number{int num[5][5];}base,ans,b;
inline number mul(number a,number b)
{
number c;
for (register int i=1; i<=2; ++i)
for (register int j=1; j<=2; ++j) c.num[i][j]=0;
for (register int i=1; i<=2; ++i)
for (register int j=1; j<=2; ++j)
for (register int k=1; k<=2; ++k)
c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j]%MOD)%MOD;
return c;
}
inline void pow(int k)
{
while (k)
{
if (k&1ll) ans=mul(ans,base);
base=mul(base,base);
k>>=1ll;
}
}
signed main(){
scanf("%lld%lld%lld%lld%lld%lld",&p,&q,&a1,&a2,&n,&MOD);
if (n<2)
{
printf("%lld\n",a1);
return 0;
}
base.num[1][1]=p; base.num[1][2]=q; base.num[2][1]=1;
for (register int i=1; i<=2; ++i) ans.num[i][i]=1;
pow(n-2);
b.num[1][1]=a2; b.num[2][1]=a1;
ans=mul(ans,b);
printf("%lld\n",ans.num[1][1]);
return 0;
}