快速幂算法
引理
- (a * b) % c = ((a % c) * (b % c)) % c.
- &与运算,一般用于取位,如 a&1表示取a二进制下的个位
- >>位运算,表示右移,如>>1表示除以2,比通常除法效率更高
- ab=ab0∗ab1∗2∗...∗abn∗2n
用途
主要用于大数取模
朴素算法存在效率太低和计算过程中超出数据范围的情况,必须进行优化
代码
int quick_pow(int a, int k, int mod)
{
int ans = 1;
a = a % mod;
while(k != 0)
{
if(k & 1) ans = (ans * a) % mod;
k >>= 1;
a=(a * a) % mod;
}
return ans;
}
int qow(int x, int y, int z)
{return y ? (y & 1 ? x * qow(x, y-1,z) % z : qow(x * x % z, y / 2,z)) : 1;}
拓展——矩阵快速幂
对于矩阵的定义以及矩阵乘法,就不多赘述了,直接切入正题
思路
矩阵快速幂和普通快速幂过程是一样的,只要将对应的运算规则变成矩阵运算规则就好。这里我选择重载运算符,当然也可以写个函数来实现。
而矩阵一般会选择封装起来,我对C++不是很熟悉,更倾向于用结构体来封装。
代码
//k,mod,maxn为全局变量
struct Mat
{
ll f[maxn][maxn];
void cls(){memset(f, 0, sizeof(f));}//全部置为0
Mat() {cls();}
friend Mat operator * (Mat a, Mat b)
{
Mat res;
for(int i = 0; i < maxn; i++) for(int j = 0; j < maxn; j++)
for(int k = 0; k < maxn; k++)
(res.f[i][j] += a.f[i][k] * b.f[k][j]) %= mod;
return res;
}
};
Mat quick_pow(Mat a)
{
Mat ans;
for(int i = 0; i < maxn; i++) ans.f[i][i] = 1;
int b = k;
while(b != 0)
{
if(b & 1) ans = ans * a;
b >>= 1;
a = a * a;
}
return ans;
}
应用
讲了矩阵快速幂之后,这个东西到底有什么用呢?
众所周知的斐波那契数列fn=fn−1+fn−2就可以用矩阵快速幂优化。
[fnfn−1fn−1fn−2]=[fn−1fn−2fn−2fn−3][1110]=[1110]n
(1)式就可以用矩阵快速幂在Olog(n)内算出来
习题
POJ 3070
HDOJ 1575
POJ 3233
HDOJ 2604
HDOJ 1757
ZOJ 3497
ZOJ 2853
总结
快速幂说复杂也挺抽象(对我这个蒟蒻来说),说简单也不难。
仔细体会其中后就能发现其中的思想很巧妙很漂亮,需要用心理解。
顺便一提,快速幂是快速算乘方运算的,过程中可以加上取模运算,实现题目要求,当然也可以不取模。不要误以为快速幂只是用来解决要取模的问题。
实际上,取模应当是快速幂中一个比较费时的计算,虽然我们只需要写一行代码。
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· ASP.NET Core 模型验证消息的本地化新姿势
· 对象命名为何需要避免'-er'和'-or'后缀
· SQL Server如何跟踪自动统计信息更新?
· AI与.NET技术实操系列:使用Catalyst进行自然语言处理
· 分享一个我遇到过的“量子力学”级别的BUG。
· 为什么AI教师难以实现
· 如何让低于1B参数的小型语言模型实现 100% 的准确率
· AI Agent爆火后,MCP协议为什么如此重要!
· 【译】Visual Studio(v17.13)中新的调试和分析特性
· Draw.io:你可能不知道的「白嫖级」图表绘制神器