uva-11149 倍增法矩阵快速幂

本文介绍了一种使用矩阵快速幂结合倍增法求解等比矩阵和的有效方法。通过具体的C++代码实现,展示了如何高效地进行矩阵运算及等比数列求和,并附带了解题思路和技术细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目的意思比较好理解,就是求等比矩阵的和,然后训练赛上,去怼矩阵快速幂,然后没怼过,超时,后来比赛结束,说是倍增法加矩阵快速幂去学了了一波,发现高中都学过,看来就是自己不会用,先说一下倍增法用来求等比数列求和,是一种速度比较快的方法,

下面介绍一下倍增法的原理的值。对于这个问题,用二分解决比较好。

(1)时,

(2)时,那么有

    

(3)时,那么有

   

真的是学到了

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

int n,m;
struct mat
{
    int a[45][45];
    mat()
    {
        memset(a,0,sizeof(a));
    }
};

mat A;
mat I;

mat add(mat m1,mat m2)
{
    mat ans;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            ans.a[i][j]=(m1.a[i][j]+m2.a[i][j])%10;
    return ans;
}
mat mul(mat m1,mat m2)
{
    mat ans;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            //if(m1.a[i][j])
                for(int k=1; k<=n; k++)
                    ans.a[i][j]=(ans.a[i][j]+m1.a[i][k]*m2.a[k][j])%10;
    return ans;
}
mat quickmul(mat m,int k)
{
    mat ans=I;
    while(k)
    {
        if(k&1) ans=mul(ans,m);
        m=mul(m,m);
        k>>=1;
    }
    return ans;
}
void print(mat m)
{
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            printf("%d%c",m.a[i][j],j==n? '\n':' ');
}

mat getsum(int k)
{
    if(k==1) return A;
    mat ans=getsum(k/2);
    if(k&1)
    {
        mat t=quickmul(A,k/2+1);
        ans=add(mul(add(I,t),ans),t);
    }
    else
    {
        mat t=quickmul(A,k/2);
        ans=mul(add(I,t),ans);
    }
    return ans;
}

int main()
{
    while(scanf("%d%d",&n,&m),n)
    {
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                scanf("%d",&A.a[i][j]),A.a[i][j]%=10;

        for(int i=1; i<=n; i++) I.a[i][i]=1;
        mat ans=getsum(m);
        print(ans);
        puts("");
    }
    return 0;
}

下面还有不是矩阵的做法,其实可以类推就知道,这只是关键的代码

LL power(LL a,LL b)  
{  
    LL ans = 1;  
    a %= M;  
    while(b)  
    {  
        if(b & 1)  
        {  
            ans = ans * a % M;  
            b--;  
        }  
        b >>= 1;  
        a = a * a % M;  
    }  
    return ans;  
}  
  
LL sum(LL a,LL n)  
{  
    if(n == 1) return a;  
    LL t = sum(a,n/2);  
    if(n & 1)  
    {  
        LL cur = power(a,n/2+1);  
        t = (t + t * cur % M) % M;  
        t = (t + cur) % M;  
    }  
    else  
    {  
        LL cur = power(a,n/2);  
        t = (t + t * cur % M) % M;  
    }  
    return t;  
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值