矩阵系列

矩阵乘法快速米模版

#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}

把矩阵乘上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}

乘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}

这个乘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);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值