一、快速幂,作为一种求幂次方的高效算法,经常用在各种比赛题目中。以前也碰到过,实践起来也不难,但总会记不清,特此做一下记录。
原理基础篇:
首先,快速幂的思想方法是什么?
没错,是二进制。就我来看,它应用二进制的原理大概可以做出如下简述:
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;
}
扫描二维码关注公众号,回复:
3699607 查看本文章