Processing math: 100%

快速幂算法

引理

  1. (a * b) % c = ((a % c) * (b % c)) % c.
  2. &与运算,一般用于取位,如 a&1表示取a二进制下的个位
  3. >>位运算,表示右移,如>>1表示除以2,比通常除法效率更高
  4. ab=ab0ab12...abn2n

用途

主要用于大数取模
朴素算法存在效率太低和计算过程中超出数据范围的情况,必须进行优化

代码

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=fn1+fn2就可以用矩阵快速幂优化。

[fnfn1fn1fn2]=[fn1fn2fn2fn3][1110]=[1110]n

(1)式就可以用矩阵快速幂在Olog(n)内算出来

习题

POJ 3070
HDOJ 1575
POJ 3233
HDOJ 2604
HDOJ 1757
ZOJ 3497
ZOJ 2853

总结

快速幂说复杂也挺抽象(对我这个蒟蒻来说),说简单也不难。
仔细体会其中后就能发现其中的思想很巧妙很漂亮,需要用心理解。
顺便一提,快速幂是快速算乘方运算的,过程中可以加上取模运算,实现题目要求,当然也可以不取模。不要误以为快速幂只是用来解决要取模的问题。
实际上,取模应当是快速幂中一个比较费时的计算,虽然我们只需要写一行代码。

posted @   HackHarry  阅读(207)  评论(0编辑  收藏  举报
编辑推荐:
· ASP.NET Core 模型验证消息的本地化新姿势
· 对象命名为何需要避免'-er'和'-or'后缀
· SQL Server如何跟踪自动统计信息更新?
· AI与.NET技术实操系列:使用Catalyst进行自然语言处理
· 分享一个我遇到过的“量子力学”级别的BUG。
阅读排行:
· 为什么AI教师难以实现
· 如何让低于1B参数的小型语言模型实现 100% 的准确率
· AI Agent爆火后,MCP协议为什么如此重要!
· 【译】Visual Studio(v17.13)中新的调试和分析特性
· Draw.io:你可能不知道的「白嫖级」图表绘制神器
点击右上角即可分享
微信分享提示