快速幂算法

一.主要功能

–>快速幂算法能帮我们算出指数非常大的幂,传统的求幂算法之所以时间复杂度非常高,就是因为当指数n非常大的时候,需要执行的循环操作次数也非常大。所以快速幂算法的核心思想就是每一步都把指数分成两半,而相应的底数做平方运算。这样不仅能把非常大的指数给不断变小,所需要执行的循环次数也变小。

二.关于取余的重要性质

1.指数较大时题中通常会有一个取余运算,而取余主要包括以下三个性质

1).(a + b) % p = (a % p + b % p) % p 

2).(a - b) % p = (a % p - b % p ) % p 

3).(a * b) % p = (a % p * b % p) % p 

2.也就是在中间运算过程中就可以同时做取余运算,防止最后的数值过大。

三、经典例题

Question:HDU1575求矩阵的迹
在这里插入图片描述

1. 矩阵快速幂

–>只需记录当指数为奇数时的底数值即可。

Matrix fastPower(Matrix base, int power, int modulus) //矩阵快速幂运算
{
	Matrix result(1);
	result.n = base.n;
	while (power > 0)
	{
		if (power % 2 == 0)
		{
			power /= 2;
			base = base * base;
		}

		else
		{
			power -= 1;
			result = result * base;
			power /= 2;
			base = base * base;
		}
	}

	return result;
}


2.关于快速幂部分还可以使用位运算优化

Matrix fastPower(Matrix base, int power, int modulus) //矩阵快速幂运算
{
	Matrix result(1);
	result.n = base.n;
	while (power)
	{
		if (power & 1)      //与1相与可以判断是否为奇数
		    result = result * base;

		power >>= 1;
		base = base * base;
	}

	return result;
}

3.完整代码展示:

#include <iostream>
#include <stdio.h>
using namespace std;

const int MaxSize = 12;

class Matrix{
public:
	int data[MaxSize][MaxSize];
	int n;
public:
	Matrix()
	{
		n = 0;
		for (int i = 0; i < MaxSize; ++ i)
			for (int j = 0; j < MaxSize; ++ j)
				data[i][j] = 0;
	}
	Matrix (int initial)       //注意在创建单位矩阵的时候不要只管data[i][i] = 1;还需要剩下的位置赋0值。自己评测的时候因为这个查了 很久!!!
	{
		n = 0;
		for (int i = 0; i < MaxSize; ++ i)
			for (int j = 0; j < MaxSize; ++ j)
			{
				if (i == j) data[i][j] = 1;
				else data[i][j] = 0;
			}
	}
	Matrix (const Matrix& tmp)
	{
		n = tmp.n;
		for (int i = 0; i < n; ++ i)
			for (int j = 0; j < n; ++ j)
				data[i][j] = tmp.data[i][j];
	}
	Matrix operator *(const Matrix& tmp)
	{
		Matrix result;
		int Mod = 9973;
		result.n = n;
		for (int i = 0; i < n; ++ i)
			for (int j = 0; j < n; ++ j)
			{
				for (int k = 0; k < n; ++ k)
					result.data[i][j] = (result.data[i][j] +  data[i][k] * tmp.data[k][j] % Mod) % Mod;
				result.data[i][j] %= Mod;
			}
		return result;
	}

	Matrix operator %(const int modulus)
	{
		Matrix result;
		result.n = n;
		for (int i = 0; i < n; ++ i)
			for (int j = 0; j < n; ++ j)
				result.data[i][j] = data[i][j] % modulus;
		return result;
	}
	Matrix& operator =(const Matrix& tmp)  //小细节:此处返回类型应该为引用,方便连续赋值。
	{
		n = tmp.n;
		for (int i = 0; i < n; ++ i)
			for (int j = 0; j < n; ++ j)
				data[i][j] = tmp.data[i][j];
		return *this;
	}
};                                                    // 重载各类运算符

Matrix fastPower(Matrix base, int power, int modulus) //矩阵快速幂运算
{
	Matrix result(1);
	result.n = base.n;
	while (power > 0)
	{
		if (power % 2 == 0)
		{
			power /= 2;
			base = base * base;
		}

		else
		{
			power -= 1;
			result = result * base;
			power /= 2;
			base = base * base;
		}
	}

	return result;
}

void caltrace(Matrix& tmp, int n, int modulus)       //求矩阵的迹
{
	int ans = 0;
	for (int i = 0; i < n; ++ i)
		ans = (ans + tmp.data[i][i]) % modulus;
	cout << ans % modulus << endl;
	return;
}

int main()
{
	freopen("in.txt", "r", stdin);

	int n, k;
	cin >> n >> k;
	Matrix m;
	for (int i = 0; i < n; ++ i)
		for (int j = 0; j < n; ++ j)
			cin >> m.data[i][j];
	m.n = n;
	Matrix seq = fastPower(m, k, 9973);
	caltrace(seq, n, 9973);
	return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Eternal_U

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值