【算法学习之路】4.简单数论(2)

简单数论(2)

  • 前言
  • 二.快速幂
    • 1.什么是快速幂
    • 2.前置知识
      • 2.1进制转化
      • 2.2短除法
      • 2.3普通转换法
    • 3.快速幂
      • 3.1原理
      • 3.2代码
    • 4.拓展
      • 4.1模运算法则
      • 4.2题目

前言

我会将一些常用的算法以及对应的题单给写完,形成一套完整的算法体系,以及大量的各个难度的题目,目前算法也写了几篇,滑动窗口的题单正在更新,其他的也会陆陆续续的更新,希望大家点赞收藏我会尽快更新的!!!

二.快速幂

1.什么是快速幂

快速幂是一种用于高效计算幂运算的算法。在普通的幂运算中,如果直接按照定义去计算,当指数很大时,需要进行次乘法运算。而快速幂算法可以显著减少计算次数。可以快速求n ^ x。

2.前置知识

2.1进制转化

任何数都可以写成 2 ^ n相加的形式。

十进制转化二进制:
7 = 2 ^ 2 + 2 ^ 1 + 2 ^ 0;
5 = 2 ^ 2 + 0 * 2 ^ 1 + 2 ^ 0;

2.2短除法

短除法:短除法是一种用于分解质因数等运算的方法。

2.3普通转换法

利用短除法加上十进制转换为二进制便可得到如图所示:
【算法学习之路】4.简单数论(2)_第1张图片
转换成代码为:

#include 

using namespace std;

int n, x;
int b[10005];//将二进制存到数组中


int main() {
	cin >> x;//读取十进制数
	if (x == 0) {
		cout << 0;
	}
	while (x != 0) {//利用短除法将十进制转化成二进制
		b[n++] = x % 2;
		x /= 2;
	}

	for (int i = n - 1; i >= 0; i--) {
		cout << b[i];
	}
 
	return 0;
}

这就是普通转换法。其时间复杂度为O(n)。

3.快速幂

3.1原理

10 = 2 ^ 3 + 2 ^ 1
5 ^ 10 = 5 ^ (8 + 2) = 5 ^ 8 * 5 ^2

1.有一个数为n的x次方,如果我们以n为底数那么此题中就变成了 n ^ 1,n ^ 2, n ^ 4,我们只需要n *= n即可。
2.如果 x % 2 == 1,证明该二进制的值为1,因此需要用答案(ans)乘上n。如:
【算法学习之路】4.简单数论(2)_第2张图片

3.2代码

#include 

using namespace std;

int n, x, j;
int ans = 1;

int main() {
	cin >> n >> x;//n为底数,x为指数
	
	while (x != 0) {
		j = x % 2;
		if (j == 1) {//当x % 2 == 1 说明在这个次数上要ans *= n
			ans *= n;
		}
		n *= n;
		x /= 2;
	}
	cout << ans;

	return 0;
}

这就是快速幂代码,其时间复杂度为O(log n)。

4.拓展

4.1模运算法则

(a + b) % c = ((a % c) + (b % c)) % c
(a - b) % c = ((a % c) - (b % c)) % c
(a * b) % c = ((a % c) * (b % c)) % c
除法的模运算法则比较特殊在这里不讨论

模运算法则原理:

(a * b) % c = ((a % c ) * (b % c)) % c
(a % c) = x --> a = i * c + x;
(b % c) = y --> b = j * c + y;
((a % c ) * (b % c)) % c = (x* y) % c;
(a * b) % c = (i * c * j * c + x * j * c + i * c * y + x * y) % c = (x * y) % c;

4.2题目

洛谷P1226 【模板】快速幂
【算法学习之路】4.简单数论(2)_第3张图片

#include 

using namespace std;

long long n, x, j, p;
long long ans = 1;

int main() {
	cin >> n >> x >> p;
	long long a = n, b = x;//先记录n,x的值,因为后面n,x的值要变化

	while (x != 0) {
		j = x % 2;
		if (j == 1) {
			ans = (ans * n) % p;//模运算规则
		}
		n = (n * n) % p;
		x /= 2;
	}
	cout << a << "^" << b << " mod " << p << "=" << ans % p << endl;//要按照输出规则来

	return 0;
}

你可能感兴趣的:(算法学习之路,算法,学习,数据结构,笔记,经验分享)