快速幂总结及应用拓展(矩阵为例)

一、快速幂,作为一种求幂次方的高效算法,经常用在各种比赛题目中。以前也碰到过,实践起来也不难,但总会记不清,特此做一下记录。

原理基础篇:

首先,快速幂的思想方法是什么?

没错,是二进制。就我来看,它应用二进制的原理大概可以做出如下简述:

1.首先我们知道,任何一个数都可以表示成二进制(计算机就是如此)。这个事实就提供了一种思路:将n次幂表示为二进制数。例如,n=13,二进制是1101。这样的话,n=8+4+1;实现了将n 分解成可由2的幂级数的和(也就是原m^n分解为乘积(n^13=n^8*n^4*n^1));

2.知道了这种应用,就很容易理解为什么快速幂这么快(logn),它的实现,个人理解就是充分利用已知的结论服务下一步操作。比如,当你求出n^4时,你只需一步 n^8=n^4*n^4 即可。

下面给出一个简单的C++模板:

int pow(int a,int n)//返回值类型根据具体问题可变
{
    int base=a;
    int ans=1;
    while(n!=0)
    {
        if(n%2)
            ans*=base;//当前位置二进制为1,
        base*=base;//实现充分利用已知结果
        n/=2;
    }
    return ans;

}

拓展篇:

学过线代的都知道怎么求矩阵的乘积,相当的有套路,但是却有显得麻烦。尤其是,当你需要对一个方阵求n次方的时候,绝望的不只是你,可能还有计算机。所以就有了优化策略,这种策略就是快速幂,原理一样,只是需要自己实现一个能完成两个方阵相乘的函数即可。

样例如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn=100+5;
int n;
void multipicate(long long p[][maxn],long long b[][maxn])
{

    long long a[maxn][maxn];
    memset(a,0,sizeof a);

    for(int i=0;i<n;i++)//经典矩阵乘法
    {
        for(int j=0;j<n;j++)
        {

            for(int k=0;k<n;k++)
            {
                a[i][j]+=(p[i][k]*b[k][j]);
            }

        }
    }
    for(int i=0;i<n;i++)
     for(int j=0;j<n;j++)
        p[i][j]=a[i][j];
}
void quick(long long p[][maxn],int m)
{
    long long base[maxn][maxn];//复制

    for(int i=0;i<n;i++)
    {

        for(int j=0;j<n;j++)
        {
         base[i][j]=p[i][j];
         if(i==j)
            p[i][j]=1;
         else
            p[i][j]=0;
        }
    }
    //快速幂
    while(m!=0)
    {
        if(m%2)
             multipicate(p,base);//s=s*base;
        multipicate(base,base);
        m/=2;
    }
}
int main()
{
    int m;
    long long s[maxn][maxn];
    cout<<"输入方阵规模和乘方规模: "<<endl;
    cin>>n>>m;
    cout<<"收入方阵数据: "<<endl;
    clock_t start,end1;
    start=clock();

    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
            cin>>s[i][j];
    }
    quick(s,m);
    cout<<"结果是: "<<endl;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
            cout<<s[i][j]<<" ";
        cout<<endl;
    }
    cout<<"时间"<<((clock()-start)/CLOCKS_PER_SEC)<<endl;
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值