快速幂&矩阵快速幂


快速幂

原理

(a^b)

例如,(b=11)时,其二进制为(1011),又有(11=2^3 imes 1+2^2 imes 0+2^1 imes 1+2^0 imes 1)

所以

[a^{11}=a^{2^3+2^1+2^0}​ ]

从而

[a^{11}=a^{2^3} imes a^{2^1} imes a^{2^0}​ ]

代码

long long quickpower(long long x,long long y)
{
    long long ans=1,cnt=x;
    while(y)
    {
        if(y&1) ans*=cnt;
        //判断y的二进制数的末位是否为0,若为0则舍弃(0作乘数结果仍为0)
        cnt*=cnt;
        y>>=1;
        //右移一位,相当于除以2
    }
    return ans;
}

最初(ans=1,cnt=a,y=1011)

(1011&1)为真,(a^1)这一位要算入,乘入(ans)。然后(a)自乘变为(a^2)(y)右移一位

(101&1)为真,(a^2)这一位要算入,乘入(ans)。然后(a)自乘变为(a^ 4)(y)右移一位

(10&1)为假,不算。然后(a)自乘变为(a^8)(y)右移一位

(1&1)为真,(a^ 8)这一位要算入,乘入(ans)。然后(a)自乘变为(a^{16})(y)右移一位

(y)(0),跳出循环


矩阵快速幂

定义矩阵

struct node {
	int mat[15][15];
}x,y;

定义矩阵乘法

node mul(node x,node y){
	node tmp;
	for(int i=0;i<len;i++){
		for(int j=0;j<len;j++){
			tmp.mat [i][j]=0;
			for(int k=0;k<len;k++) tmp.mat [i][j] += x.mat [i][k] * y.mat[k][j];
            //x,y是相同的k阶方阵
		}
	}
	return tmp;
}

也可以将二者合并,在结构体中重载运算符

struct matrix{
	ll a1,a2,b1,b2;
	matrix operator*(const matrix &y)//重载乘号运算符
    {
        matrix ans((a1 * y.a1 + a2 * y.b1),
                   (a1 * y.a2 + a2 * y.b2),
                   (b1 * y.a1 + b2 * y.b1),
                   (b1 * y.a2 + b2 * y.b2));
        return ans;
    }
};

矩阵快速幂

node matpow(node x,int num){
    //num为幂
    node ans(1, 0, 0, 1);//单位矩阵
	while(num){
		if(num&1){
			ans=mul(ans,x);
		}
		x=mul(x,x);
		num=num>>1;
	}
	return ans;
}
原文地址:https://www.cnblogs.com/streamazure/p/12803813.html