快速幂与矩阵快速幂

快速幂

求ab % m=?

①a2=a*a,a4=a2*a2,可以快速算出a2,a4,a8,a16……
②b可以被二进制表示出来,例如13=1101。a13就可以被拆为a8*a4*a1
③ab % m ==(a % m)b % m,也就是说可以提前模a减少a的规模。

③的证明过程: a%c=x → a=uc+x b%c=y → b=vc+y

ab%c=(uc+x)*(vc+y) % c
=[(uv)c2+(uy+vx)c+xy] % c
=xy % c
∴ab%c=xy%c==(a%c)(b%c)%c,可以提前取模。

int quickpow(int a,int b,int m)
{
	int ans=1;a=a%m;
	while(b)
	{
		if(b&1) ans=(ans*a)%m;//位运算,如果b最后一位是1,则乘上a
		b>>=1;//b右移一位,相当于准备在下一轮循环中看倒数第二位是否为1
		a=(a*a)%mod;//同时a也进行幂数翻倍
	}
	return ans;
}

矩阵快速幂

矩阵也可以用快速幂,设2X2的矩阵A
A*A=A2,A2*A2=A4,并可快速求出A8,A16……
A13=A8×A4×A1

例如求斐波拉契数列的第n项

由于斐波拉契数列是f(1)=f(2)=1,f(n)=f(n-1)+f(n-2)。
递推式可以写作矩阵递推式:
( 1 1 1 0 ) × ( F n − 1 F n − 2 ) = ( F n F n − 1 ) \begin{pmatrix} 1 & 1 \\ 1 & 0 \\ \end{pmatrix}× \begin{pmatrix} F_n-1 \\ F_n-2 \\ \end{pmatrix}= \begin{pmatrix} F_n \\ F_n-1 \\ \end{pmatrix} (1110)×(Fn1Fn2)=(FnFn1)
(可以将F0=0看做是斐波拉契数列的第0项)
可以推知:
( 1 1 1 0 ) n − 1 ( F 1 F 0 ) = ( F n F n − 1 ) \begin{pmatrix} 1 & 1 \\ 1 & 0 \\ \end{pmatrix}^{n-1} \begin{pmatrix} F_1 \\ F_0 \\ \end{pmatrix}= \begin{pmatrix} F_n \\ F_n-1 \\ \end{pmatrix} (1110)n1(F1F0)=(FnFn1)
那么只要计算
( 1 1 1 0 ) n − 1 \begin{pmatrix} 1 & 1 \\ 1 & 0 \\ \end{pmatrix}^{n-1} (1110)n1
而这可则以利用上面快速幂的方法
关键代码

//a要初始化为上面那个矩阵,n是上面的n-1
int quickpow(mat a,int n)//mat内有2x2数组+矩阵乘法
{
	mat ans;//在类中用构造函数默认初始化为单位矩阵
	while(n)
	{
		if(n&1) ans=mul(ans,a);//mul是矩阵乘法函数,要自己写,三重循环
		n>>=1;//n右移一位,相当于准备在下一轮循环中看倒数第二位是否为1
		a=mul(a,a);//同时a也进行幂数翻倍
	}
	return ans;
}

得到的最后矩阵ans的ans.a[0][0]项就是斐波拉契的第n项,虽然最后还要
a n s × ( 1 0 ) = ( F n F n − 1 ) ans×\begin{pmatrix} 1 \\ 0 \\ \end{pmatrix}= \begin{pmatrix} F_n \\ F_n-1 \\ \end{pmatrix} ans×(10)=(FnFn1)但很显然Fn的值就是ans.a[0][0]。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值