相信我们都做过一个题叫斐波那契数列,对于一般的题,n的取值范围通常在1000以内,但是如果你遇到的是下面这题呢?
发现了吗?我的n取值范围连long long都会爆出,所以下面我们通过矩阵乘法和快速幂结合来解决该类问题,如果你不知道矩阵乘法和快速幂,这篇文章可能不适合你
下面我们利用矩阵乘法和快速幂来解决该问题:
代码如下:
cpp
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
const ll p=1e9+7;
ll x;
const int N=2;
int n=2;
ll a[N+1][N+1],b[N+1];
void func1()
{
ll m[N+1];
memset(m,0,sizeof(m));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
m[i]+=b[j]*a[j][i];
m[i]%=p;
}
}
memcpy(b,m,sizeof(b));
}
void func2()
{
ll w[N+1][N+1];
memset(w,0,sizeof(w));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=1;k<=n;k++)
{
w[i][j]+=a[i][k]*a[k][j];
w[i][j]%=p;
}
}
}
memcpy(a,w,sizeof(a));
}
void quickpow(ll x)
{
for(;x;x>>=1)
{
if(x&1)
{
func1();
}
func2();
}
}
int main()
{
//输入
cin>>x;
//快速幂+矩阵乘法
//初始化
a[1][1]=0;a[1][2]=1;
a[2][1]=1;a[2][2]=1;
b[1]=0;b[2]=1;
quickpow(x-1);
//输出
cout<<b[2];
return 0;
}
可以优化:
cpp
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
const ll p=1e9+7;
ll x;
const int N=2;
int n=2;
ll a[N+1][N+1],b[N+1];
void func1()
{
ll m[N+1];
memset(m,0,sizeof(m));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
m[i]+=b[j]*a[j][i];
m[i]%=p;
}
}
memcpy(b,m,sizeof(b));
}
void func2()
{
ll w[N+1][N+1];
memset(w,0,sizeof(w));
for(int i=1;i<=n;i++)
{
for(int k=1;k<=n;k++)
{
if(a[i][k])
{
for(int j=1;j<=n;j++)
{
if(a[k][j])
{
w[i][j]+=a[i][k]*a[k][j];
w[i][j]%=p;
}
}
}
}
}
memcpy(a,w,sizeof(a));
}
void quickpow(ll x)
{
for(;x;x>>=1)
{
if(x&1)
{
func1();
}
func2();
}
}
int main()
{
//输入
cin>>x;
//快速幂+矩阵乘法
//初始化
a[1][1]=0;a[1][2]=1;
a[2][1]=1;a[2][2]=1;
b[1]=0;b[2]=1;
quickpow(x-1);
//输出
cout<<b[2];
return 0;
}
下面我们给出矩阵乘法和快速幂结合模版,该类问题解题关机是构造矩阵
cpp
using ll = long long;
const ll N = 2;//实际情况修改
int n = 2;
ll a[N + 1][N + 1], b[N + 1];
const ll p = 1e8 + 7;//取模的值
void func1()
{
ll m[N + 1];
//清空
memset(m, 0, sizeof(m));
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
m[i] += a[j][i] * b[j];
m[i] %= p;
}
}
memcpy(b, m, sizeof(b));
}
void func2()
{
ll w[N + 1][N + 1];
memset(w, 0, sizeof(w));
/*for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
for (int k = 1; k <=n; k++)
{
w[i][j] += a[i][k] * a[k][j];
w[i][j] %= p;
}
}
}*/
//优化:
for (int i = 1; i <= n; i++)
{
for (int k = 1; k <= n; k++)
{
if (a[i][k])
{
for (int j = 1; j <= n; j++)
{
if (a[k][j])
{
w[i][j] += a[i][k] * a[k][j];
w[i][j] %= p;
}
}
}
}
}
memcpy(a, w, sizeof(a));
}
void quickpow(ll x)
{
for (; x; x >>= 1)
{
if (x & 1)
{
func1();
}
func2();
}
}
关于这类问题,很多网址都有大量题目,大家可以自行去学习,感谢大家的支持!!!