快速幂是指在O(log n)的时间内计算的简便运算,而暴力的计算需要O(n)的时间。它可以应用于模意义下取幂、矩阵幂等运算。
一、算法描述:
= a * a * a * …… * a (n个a)
若 b+c=n 则 =
二进制取幂的想法是:我们将取幂的任务按照指数的二进制表示来分割成更小的任务。
= = * * = * *
因为n有 log2 n+1 个二进制位,因此我们只用计算log n次乘法就可以计算出 。
二、代码实现:
1.非递归版本(常用方法):
long long ksm(long long a,long long b,long long p){//快速幂的计算结果一般会爆int
int c=1;
while(b){
if(b&1){//位运算
c=c*a%p;//一定记得要模除
}
a=a*a%p;
b>>=1;
}
return c;
}
2.递归版本:
long long ksm(int a,int b,int p){
if(!b)return 1;
if(b&1)return (power(a,b-1,p)*a)%p;
int cnt=power(a,b/2,p)%p;
return (cnt*cnt)%p;
}
三、矩阵快速幂:
矩阵乘法:
#include <iostream>
#include <cmath>
using namespace std;
int a[1001][1001],b[1001][1001],c[1001][1001];
int main(){
int n,m,k;
cin >>n>>m>>k;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)cin >>a[i][j];
}
for(int i=1;i<=m;i++){
for(int j=1;j<=k;j++)cin >>b[i][j];
}
for(int i=1;i<=n;i++){
for(int j=1;j<=k;j++){
for(int o=1;o<=m;o++){
c[i][j]+=a[i][o]*b[o][j];
}
}
}
//C[i][j] = A[i][0]×B[0][j] + A[i][1]×B[1][j] + …… +A[i][m-1]×B[m-1][j]
for(int i=1;i<=n;i++){
for(int j=1;j<=k;j++){
cout <<c[i][j]<<" ";
}
cout <<endl;
}
//A[i][0]×B[0][j]
return 0;
}
接着使用快速幂的思想往下推就可以了。
四、真题演练:(洛谷 P1226【模板】快速幂||取余运算):
题目描述:
给你三个整数 a,b,p,求mod p。
输入格式:
输入只有一行三个整数,分别代表 a,b,p。
输出格式:
输出一行一个字符串 a^b mod p=s
,其中 a,b,p 分别为题目给定的值,s 为运算结果。
输入样例:
2 10 9
输出样例:
2^10 mod 9=7
说明、提示:
数据规模与约定:
对于 100% 的数据,保证 。
思路:
一道简单的模板题。
实现:
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <cstring>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <cstdio>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <list>
#include <map>
using namespace std;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
#define LL long long
LL power(LL a , LL b , LL mod)
{
LL ans = 1;
while(b)
{
if(b&1) ans = (ans * a)%mod;
b >>= 1;
a = (a * a )% mod;
}
return ans;
}
int main()
{
LL a,b,mod;
cin >> a >> b >> mod;
LL ans = power(a,b,mod);
printf("%lld^%lld mod %lld=%lld\n",a,b,mod,ans);
return 0;
}