矩阵乘法快速米模版
#include<cstdio>
using namespace std;
long long n,m;
struct st{
long long a[105][105];
inline st operator *(const st &b)const
{
st ans;
for (long long i=1;i<=n;i++)
for (long long j=1;j<=n;j++)
{
ans.a[i][j]=0;
for (long long k=1;k<=n;k++)
(ans.a[i][j]+=a[i][k]*b.a[k][j])%=1000000007;
}
return ans;
}
}q;
st fastpow(st a,long long m)
{
st ans=a;m--;
while(m)
{
if(m%2==1)
ans=a*ans;
a=a*a;
m/=2;
}
return ans;
}
int main(){
scanf("%lld%lld",&n,&m);
for(long long i=1;i<=n;i++)
for(long long j=1;j<=n;j++)scanf("%lld",&q.a[i][j]);
q=fastpow(q,m);
for(long long i=1;i<=n;i++)
{for(long long j=1;j<=n;j++)
printf("%lld ",q.a[i][j]);
printf("\n");
}
}
广义斐波那契亚数列
广义,不过是把矩阵换了换而已,只需要把原来的改几个初始值就过了
{ f(n),f(n-1) } = { f(n-1),f(n-2) }*{n,1 }
{ m,0}
{ m,0}
把矩阵乘上n-2次在乘{a1,a2}就行了
#include<cstdio>
using namespace std;
long long n,m,b,c,a1,a2;
struct st{
long long a[5][5];
inline st operator *(const st &b)const
{
st ans;
for (long long i=1;i<=2;i++)
for (long long j=1;j<=2;j++)
{
ans.a[i][j]=0;
for (long long k=1;k<=2;k++)
(ans.a[i][j]+=(a[i][k]*b.a[k][j]%m))%=m;
}
return ans;
}
}q;
st fastpow(st a,long long n)
{
st ans=a;n--;
while(n)
{
if(n%2==1)
ans=a*ans;
a=a*a;
n/=2;
}
return ans;
}
int main(){
scanf("%lld%lld%lld%lld%lld%lld",&b,&c,&a1,&a2,&n,&m);
if(n==1)
{
printf("%lld",a1%m);
return 0;
}
if(n==2)
{
printf("%lld",a2%m);
return 0;
}
q.a[1][1]=b;q.a[1][2]=1;q.a[2][1]=c;q.a[2][2]=0;
q=fastpow(q,n-2);
printf("%lld",(a2*q.a[1][1]%m+a1*q.a[2][1]%m)%m);
}
矩阵加速
这个题和前一个差不多,只不过矩阵变成三维的了
---------------------------------------------------{1,1,0}
{ f(n),f(n-1),f(n-2) } = { f(n-1),f(n-2),f(n-3) }*{0,0,1 }
{ 1,0,0}
{ f(n),f(n-1),f(n-2) } = { f(n-1),f(n-2),f(n-3) }*{0,0,1 }
{ 1,0,0}
乘n-3次,再乘上{f1,f2,f3};
#include<cstdio>
using namespace std;
long long n,m,b,c,a1,a2;
struct st{
long long a[5][5];
inline st operator *(const st &b)const
{
st ans;
for (long long i=1;i<=3;i++)
for (long long j=1;j<=3;j++)
{
ans.a[i][j]=0;
for (long long k=1;k<=3;k++)
(ans.a[i][j]+=(a[i][k]*b.a[k][j]%1000000007))%=1000000007;
}
return ans;
}
}q;
st fastpow(st a,long long n)
{
st ans=a;n--;
while(n)
{
if(n%2==1)
ans=a*ans;
a=a*a;
n/=2;
}
return ans;
}
long long t;
int main(){
scanf("%lld",&t);
q.a[1][1]=1;q.a[1][2]=1;q.a[1][3]=0;q.a[2][1]=0;q.a[2][2]=0;
q.a[2][3]=1;q.a[3][1]=1;q.a[3][2]=0;q.a[3][3]=0;
while(t--)
{
scanf("%lld",&n);
if(n==1||n==2||n==3) {
printf("1\n");
continue;
}
st ans=fastpow(q,n-3);
printf("%lld\n",(ans.a[1][1]+ans.a[2][1]+ans.a[3][1])%1000000007);
}
}
随机数生成器
别忘了取模,在写个快速加,防止 long long 乘起来爆炸
{ f(n),1 } = { f(n-1),1 }*{n,0 }
{ m,1}
{ m,1}
这个乘n次
#include<cstdio>
using namespace std;
long long n,m,b,c,a1,a2;long long w,x,g;
long long fastjia(long a,long long n)
{
long long ans=0;
while(n)
{
if(n%2==1)
ans=(a+ans)%m;
a=(a+a)%m;
n/=2;
}
return ans%m;
}
struct st{
long long a[5][5];
inline st operator *(const st &b)const
{
st ans;
for (long long i=1;i<=2;i++)
for (long long j=1;j<=2;j++)
{
ans.a[i][j]=0;
for (long long k=1;k<=2;k++)
(ans.a[i][j]+=(fastjia(a[i][k],b.a[k][j])%m))%=m;
}
return ans;
}
}q;
st fastpow(st a,long long n)
{
st ans=a;n--;
while(n)
{
if(n%2==1)
ans=a*ans;
a=a*a;
n/=2;
}
return ans;
}
int main(){
scanf("%lld%lld%lld%lld%lld%lld",&m,&w,&c,&x,&n,&g);
if(n==0)
{
printf("%lld",x%m%g);
return 0;
}
q.a[1][1]=w%m;q.a[1][2]=0;q.a[2][1]=c;q.a[2][2]=1;
q=fastpow(q,n);
printf("%lld",(fastjia(x,q.a[1][1])+q.a[2][1]%m)%m%g);
}