进阶数据结构——高精度运算

news2025/2/2 5:33:29

目录

  • 前言
  • 一、高精度运算的定义与背景
  • 二、高精度运算的实现方式
  • 三、高精度运算的算法实现
  • 四、高精度运算的应用场景
  • 五、代码模版(c++)
  • 六、经典例题
    • 1.[高精度加法](https://www.lanqiao.cn/problems/1516/learning/?page=1&first_category_id=1&name=%E9%AB%98%E7%B2%BE%E5%BA%A6%E5%8A%A0%E6%B3%95)
    • 3.[高精度减法](https://www.luogu.com.cn/problem/P2142)
    • 3.[高精度乘法](https://www.lanqiao.cn/problems/1515/learning/?page=1&first_category_id=1&name=%E9%98%B6%E4%B9%98%E8%AE%A1%E7%AE%97)
    • 4.[高精度除法](https://www.luogu.com.cn/problem/P1480)
  • 七、总结
  • 结语

前言

从这期开始我们就开始进入进阶数据结构的学习了。进阶数据结构中的高精度运算分析,主要聚焦于如何在计算机编程中有效处理超出常规数据类型表示范围的极大或极精确数值。

在这里插入图片描述

一、高精度运算的定义与背景

高精度运算是指在计算机编程中,对超出常规数据类型(如整型、浮点型)所能表示范围的极大或极精确数值进行的各种数学运算。在标准的计算机编程语言中,内置的整数和浮点数类型有其固定的字节数和精度限制,一旦数字过大或精度过高,就会导致溢出或精度丢失的问题。因此,高精度运算技术应运而生。

二、高精度运算的实现方式

高精度运算的实现方式通常涉及自定义数据结构来存储极大数值的每一位。这些数据结构能够模拟人类手算时多位数列的运算规则,使得在理论上能够处理任意长度和精度的数字。常见的实现方式包括:
数组:数组是最常用的数据结构之一,在高精度运算中,可以使用数组来存储每一位数字。例如,在C++中,可以使用std::vector或std::deque等动态数组来分别存储每一位数字。这种方式的好处是访问和修改数字的各个位非常方便,且能够处理任意长度的数字。
字符串:在某些情况下,也可以使用字符串来表示高精度数。字符串的好处是能够直接输入和输出,且不需要考虑数字的位数和进位问题。但是,字符串中的每一位是一个字符,不能直接进行运算,必须先将它转化为数值再进行运算,这增加了运算的复杂性。

三、高精度运算的算法实现

高精度运算的算法实现包括加、减、乘、除等基本运算。以下是对这些运算的简要分析:

加法:高精度加法的基本思想是将两个加数和被加数数组从第一位开始对其,并从第一位开始向后遍历,每一位相加并判断进位,直至到达输入数据末端为止。最后,如果最高位有进位,则需要添加一位。
减法:高精度减法与加法类似,但需要注意处理借位问题。当被减数小于减数时,需要向前一位借位。借位的过程可以通过在该位加上10并减去下一位的值来实现。同时,需要注意处理结果的符号和前导零。
乘法:高精度乘法的基本思想是两个数组相对应位置的数字相乘并考虑进位。可以使用双重循环来遍历两个数组的每一位,并将乘积累加到结果数组中。最后,需要处理进位问题。
除法:高精度除法相对复杂,通常使用长除法或更高效的算法如Karatsuba算法等来实现。除法的关键是逐位确定商的值,并通过减法来确定余数。由于除法运算的复杂性,实现时需要注意处理各种边界情况和异常情况。

四、高精度运算的应用场景

高精度运算在许多领域都有广泛的应用场景,包括但不限于:

科学计算:在科学计算中,经常需要处理小数点后几百位甚至更多的数字,高精度运算能够提供必要的精度和范围支持。
金融计算:在金融领域,高精度运算用于处理大额货币交易和精确计算利息等金融指标。
密码学:在密码学中,高精度运算用于实现加密算法和生成大素数等安全操作。
计算机图形学:在计算机图形学中,高精度运算用于处理浮点数运算中的精度丢失问题,以确保图形的精确渲染。

五、代码模版(c++)

六、经典例题

1.高精度加法

蓝色字体点进去看原题
蓝色字体点进去看原题
蓝色字体点进去看原题

#include<iostream>
#include<cstring>
using namespace std;

const int Base = 1000;			//进制数
const int Capacity = 100;		//数组容量

class BigInt {
private:
	int m_size;
	int m_data[Capacity];

	void removeLendingZero();				//去除前导0
public:
	BigInt(int v);				
	BigInt();								
	BigInt(char s[]);						//将数字字符串存入数据
	void print(char end);
	BigInt(const BigInt& bi);
	BigInt& operator=(const BigInt& bi);
	int compare(const BigInt& bi);

	BigInt operator+(const BigInt& bi);
	BigInt operator-(const BigInt& bi);
	BigInt operator*(const BigInt& bi);
	BigInt operator/(const BigInt& bi);
};

BigInt::BigInt() {
	m_size = 0;
	memset(m_data, 0, sizeof(m_data));
}

BigInt::BigInt(int v) {
	m_size = 0;
	while (v > 0) {
		m_data[m_size++] = v % Base;
		v /= Base;
	}
}

BigInt::BigInt(char s[]) {
	m_size = 0;
	int b = 1;
	memset(m_data, 0, sizeof(m_data));
	for (int i = strlen(s) - 1; i >= 0; i--) {
		m_data[m_size] += (s[i] - '0') * b;
		b *= 10;
		if (b >= Base) {
			b = 1;
			m_size++;
			m_data[m_size] = 0;
		}
	}
	if (m_data[m_size] > 0) m_size++;
	removeLendingZero();
}

BigInt::BigInt(const BigInt& bi) {
	m_size = bi.m_size;
	memcpy(m_data, bi.m_data, sizeof(bi.m_data));
}

BigInt& BigInt::operator=(const BigInt& bi) {
	m_size = bi.m_size;
	memcpy(m_data, bi.m_data, sizeof(m_data));
	return *this;
}

void BigInt::print(char end) {
	cout << (m_size == 0 ? 0 : m_data[m_size - 1]);
	for (int i = m_size - 2; i >= 0; i--) {
		for (int j = Base / 10; j > 0; j /= 10) {
			cout << (m_data[i] / j) % 10;
		}
	}
	cout << end;
}

void BigInt::removeLendingZero() {
	while (m_size > 0 && m_data[m_size - 1] == 0) {
		m_size--;
	}
}

int BigInt::compare(const BigInt& bi) {
	if (m_size != bi.m_size)return m_size > bi.m_size ? 1 : -1;
	for (int i = m_size - 1; i >= 0; i--) {
		if (m_data[i] != bi.m_data[i]) return m_data[i] > bi.m_data[i] ? 1 : -1;
	}
	return 0;
}

BigInt BigInt::operator+(const BigInt& bi) {
	BigInt ret;
	int carry = 0, i;
	for (i = 0; i < bi.m_size || i < m_size || carry > 0 ; i++) {
		/*if (i < m_size)*/carry += m_data[i];
		/*if (i < bi.m_size)*/carry += bi.m_data[i];
		ret.m_data[i] = carry % Base;
		carry /= Base;
	}
	ret.m_size = i;		//注意此时ret的长度就是为i
	return ret;
}

int main() {
	char s1[1000], s2[1000];
	while (cin >> s1 >> s2) {
		BigInt a(s1), b(s2);
		(a + b).print('\n');
	}


	return 0;
}

3.高精度减法

这一题你们要注意范围长度,还要处理负数的情况

#include<iostream>
#include<cstring>
using namespace std;

const int Base = 1000;			//进制数
const int Capacity = 10086 / 3 + 1;		//数组容量

class BigInt {
private:
	int m_size;
	int m_data[Capacity];

	void removeLendingZero();				//去除前导0
public:
	BigInt(int v);				
	BigInt();								
	BigInt(char s[]);						//将数字字符串存入数据
	void print(char end);
	BigInt(const BigInt& bi);
	BigInt& operator=(const BigInt& bi);
	int compare(const BigInt& bi);

	BigInt operator+(const BigInt& bi);
	BigInt operator-(const BigInt& bi);
	BigInt operator*(const BigInt& bi);
	BigInt operator/(const BigInt& bi);
};

BigInt::BigInt() {
	m_size = 0;
	memset(m_data, 0, sizeof(m_data));
}

BigInt::BigInt(int v) {
	m_size = 0;
	while (v > 0) {
		m_data[m_size++] = v % Base;
		v /= Base;
	}
}

BigInt::BigInt(char s[]) {
	m_size = 0;
	int b = 1;
	memset(m_data, 0, sizeof(m_data));
	for (int i = strlen(s) - 1; i >= 0; i--) {
		m_data[m_size] += (s[i] - '0') * b;
		b *= 10;
		if (b >= Base) {
			b = 1;
			m_size++;
			m_data[m_size] = 0;
		}
	}
	if (m_data[m_size] > 0) m_size++;
	removeLendingZero();
}

BigInt::BigInt(const BigInt& bi) {
	m_size = bi.m_size;
	memcpy(m_data, bi.m_data, sizeof(bi.m_data));
}

BigInt& BigInt::operator=(const BigInt& bi) {
	m_size = bi.m_size;
	memcpy(m_data, bi.m_data, sizeof(m_data));
	return *this;
}

void BigInt::print(char end) {
	cout << (m_size == 0 ? 0 : m_data[m_size - 1]);
	for (int i = m_size - 2; i >= 0; i--) {
		for (int j = Base / 10; j > 0; j /= 10) {
			cout << (m_data[i] / j) % 10;
		}
	}
	cout << end;
}

void BigInt::removeLendingZero() {
	while (m_size > 0 && m_data[m_size - 1] == 0) {
		m_size--;
	}
}

int BigInt::compare(const BigInt& bi) {
	if (m_size != bi.m_size)return m_size > bi.m_size ? 1 : -1;
	for (int i = m_size - 1; i >= 0; i--) {
		if (m_data[i] != bi.m_data[i]) return m_data[i] > bi.m_data[i] ? 1 : -1;
	}
	return 0;
}

BigInt BigInt::operator+(const BigInt& bi) {
	BigInt ret;
	int carry = 0, i;
	for (i = 0; i < bi.m_size || i < m_size || carry > 0 ; i++) {
		/*if (i < m_size)*/carry += m_data[i];
		/*if (i < bi.m_size)*/carry += bi.m_data[i];
		ret.m_data[i] = carry % Base;
		carry /= Base;
	}
	ret.m_size = i;		//注意此时ret的长度就是为i
	return ret;
}

BigInt BigInt::operator-(const BigInt& bi) {
	BigInt ret;
	int carry = 0;
	ret.m_size = m_size;
	for (int i = 0; i < m_size; i++) {
		ret.m_data[i] = m_data[i] - carry;
		if (i < bi.m_size) ret.m_data[i] -= bi.m_data[i];	//一定是判断减数的每一位减完了没有,如果没有结果值为乱数
		if (ret.m_data[i] < 0) {
			ret.m_data[i] += Base;
			carry = 1;
		}
		else carry = 0;		//注意carry一定要重新赋值为0,不然到下一位的时候carry的值就被污染了
	}

	ret.removeLendingZero();
	return ret;
}



int main() {
	char s1[100087], s2[100087];
	while (cin >> s1 >> s2) {
		BigInt a(s1), b(s2);
		if (a.compare(b) >= 0) (a - b).print('\n');
		else {
			cout << "-";
			(b - a).print('\n');
		}
	}


	return 0;
}

3.高精度乘法

#include<iostream>
#include<cstring>
using namespace std;

const int Base = 1000;			//进制数
const int Capacity = 1000;		//数组容量

class BigInt {
private:
	int m_size;
	int m_data[Capacity];

	void removeLendingZero();				//去除前导0
public:
	BigInt(int v);				
	BigInt();								
	BigInt(char s[]);						//将数字字符串存入数据
	void print(char end);
	BigInt(const BigInt& bi);
	BigInt& operator=(const BigInt& bi);
	int compare(const BigInt& bi);

	BigInt operator+(const BigInt& bi) const;
	BigInt operator-(const BigInt& bi) const;
	BigInt operator*(const BigInt& bi) const;
	BigInt operator/(const BigInt& bi) const;
};

BigInt::BigInt() {
	m_size = 0;
	memset(m_data, 0, sizeof(m_data));
}

BigInt::BigInt(int v) {
	m_size = 0;
	while (v > 0) {
		m_data[m_size++] = v % Base;
		v /= Base;
	}
}

BigInt::BigInt(char s[]) {
	m_size = 0;
	int b = 1;
	memset(m_data, 0, sizeof(m_data));
	for (int i = strlen(s) - 1; i >= 0; i--) {
		m_data[m_size] += (s[i] - '0') * b;
		b *= 10;
		if (b >= Base) {
			b = 1;
			m_size++;
			m_data[m_size] = 0;
		}
	}
	if (m_data[m_size] > 0) m_size++;
	removeLendingZero();
}

BigInt::BigInt(const BigInt& bi) {
	m_size = bi.m_size;
	memcpy(m_data, bi.m_data, sizeof(bi.m_data));
}

BigInt& BigInt::operator=(const BigInt& bi) {
	m_size = bi.m_size;
	memcpy(m_data, bi.m_data, sizeof(m_data));
	return *this;
}

void BigInt::print(char end) {
	cout << (m_size == 0 ? 0 : m_data[m_size - 1]);
	for (int i = m_size - 2; i >= 0; i--) {
		for (int j = Base / 10; j > 0; j /= 10) {
			cout << (m_data[i] / j) % 10;
		}
	}
	cout << end;
}

void BigInt::removeLendingZero() {
	while (m_size > 0 && m_data[m_size - 1] == 0) {
		m_size--;
	}
}

int BigInt::compare(const BigInt& bi) {
	if (m_size != bi.m_size)return m_size > bi.m_size ? 1 : -1;
	for (int i = m_size - 1; i >= 0; i--) {
		if (m_data[i] != bi.m_data[i]) return m_data[i] > bi.m_data[i] ? 1 : -1;
	}
	return 0;
}

BigInt BigInt::operator+(const BigInt& bi) const {
	BigInt ret;
	int carry = 0, i;
	for (i = 0; i < bi.m_size || i < m_size || carry > 0 ; i++) {
		if (i < m_size)carry += m_data[i];
		if (i < bi.m_size)carry += bi.m_data[i];
		ret.m_data[i] = carry % Base;
		carry /= Base;
	}
	ret.m_size = i;		//注意此时ret的长度就是为i
	return ret;
}

BigInt BigInt::operator-(const BigInt& bi) const {
	BigInt ret;
	int carry = 0;
	ret.m_size = m_size;
	for (int i = 0; i < m_size; i++) {
		ret.m_data[i] = m_data[i] - carry;
		if (i < bi.m_size) ret.m_data[i] -= bi.m_data[i];	//一定是判断减数的每一位减完了没有,如果没有结果值为乱数
		if (ret.m_data[i] < 0) {
			ret.m_data[i] += Base;
			carry = 1;
		}
		else carry = 0;		//注意carry一定要重新赋值为0,不然到下一位的时候carry的值就被污染了
	}

	ret.removeLendingZero();
	return ret;
}

BigInt BigInt:: operator*(const BigInt& bi) const {
	BigInt ret;
	ret.m_size = m_size + bi.m_size;
	for (int i = 0; i < ret.m_size; i++) {
		ret.m_data[i] = 0;
	}
	for (int i = 0; i < m_size; i++) {
		int carry = 0;
		for (int j = 0; j < bi.m_size; j++) {
			ret.m_data[i + j] += m_data[i] * bi.m_data[j] + carry;
			if (ret.m_data[i + j] >= Base) {
				carry = ret.m_data[i + j] / Base;
				ret.m_data[i + j] %= Base;
			}
			else carry = 0;
		}
		ret.m_data[i + bi.m_size] += carry;
	}
	ret.removeLendingZero();
	return ret;
}


int main() {
	int n;
	while (cin >> n) {
		BigInt ret(1);
		for (int i = 2; i <= n; i++) {
			ret = ret * i;
		}
		ret.print('\n');
	}
	return 0;
}

4.高精度除法

#include<iostream>
#include<cstring>
using namespace std;

const int Base = 1000;
const int Capacity = 10000;

class BigInt {
private:
	int m_data[Capacity];
	int m_size;

	void removeLeadingZeros();

public:
	BigInt();
	BigInt(int v);
	BigInt(const BigInt& bi);
	BigInt(char s[]);
	BigInt& operator=(const BigInt& bi);
	void print(char end);
	int compare(const BigInt& bi);

	BigInt operator+(const BigInt& bi) const;
	BigInt operator-(const BigInt& bi) const;
	BigInt operator*(const BigInt& bi) const;
	BigInt operator/(const BigInt& bi) const;
};

BigInt::BigInt(int v) {
	m_size = 0;
	while(v > 0) {
		m_data[m_size++] = v % Base;
		v /= Base;
	}
}

BigInt::BigInt() :m_size(0) {
	memset(m_data, 0, sizeof(m_data));
}

BigInt::BigInt(const BigInt& bi) :m_size(bi.m_size) {
	memcpy(m_data, bi.m_data, sizeof(bi.m_data));
}


BigInt::BigInt(char s[]) {
	m_size = 0;
	m_data[m_size] = 0;
	int b = 1;
	for (int i = strlen(s) - 1; i >= 0; i--) {
		m_data[m_size] += (s[i] - '0') * b;
		b *= 10;
		if (b >= Base) {
			m_size++;
			b = 1;
			m_data[m_size] = 0;
		}
	}
	if (m_data[m_size] > 0) {		//注意m_size可能会比原来多所以要判断
		m_size++;
	}
	removeLeadingZeros();
}

BigInt& BigInt::operator=(const BigInt& bi) {
	m_size = bi.m_size;
	memcpy(m_data, bi.m_data, sizeof(m_data));
	return *this;
}

void BigInt::print(char end) {
	cout << (m_size == 0 ? 0 : m_data[m_size - 1]);
	for (int i = m_size - 2; i >= 0; i--) {
		for (int j = Base / 10; j > 0; j/=10) {
			cout << (m_data[i] / j) % 10;
		}
	}
	cout << end;
}

int BigInt::compare(const BigInt& bi) {
	if (m_size != bi.m_size) {
		return m_size > bi.m_size ? 1 : -1;
	}
	for (int i = m_size - 1; i >= 0; i--) {
		if (m_data[i] != bi.m_data[i])return m_data[i] > bi.m_data[i] ? 1 : -1;
	}
	return 0;
}

void BigInt::removeLeadingZeros() {
	while (m_size > 0 && m_data[m_size - 1] == 0) {
		m_size--;
	}
}

BigInt BigInt::operator+(const BigInt& bi) const {
	BigInt ret;
	int i = 0, carry = 0;
	for (; i < m_size || i < bi.m_size || carry > 0; i++) {
		if (i < m_size) carry += m_data[i];
		if (i < bi.m_size) carry += bi.m_data[i];
		ret.m_data[i] = carry % Base;
		carry /= Base;
	}
	ret.m_size = i;

	return ret;
}

BigInt BigInt::operator-(const BigInt& bi) const {
	BigInt ret;
	int carry = 0;
	ret.m_size = m_size;		//被减数赋值给ret
	for (int i = 0; i < ret.m_size; i++) {
		ret.m_data[i] = m_data[i] - carry;
		if (i < bi.m_size) ret.m_data[i] -= bi.m_data[i];
		if (ret.m_data[i] < 0) {
			carry = 1;
			ret.m_data[i] += Base;
		}
		else {
			carry = 0;
		}
	}
	ret.removeLeadingZeros();
	return ret;
}

BigInt BigInt::operator*(const BigInt& bi) const {
	BigInt ret;
	ret.m_size = m_size + bi.m_size;
	for (int i = 0; i < ret.m_size; i++) {
		ret.m_data[i] = 0;
	}
	for (int i = 0; i < m_size; i++) {
		int carry = 0;
		for (int j = 0; j < bi.m_size; j++) {
			ret.m_data[i + j] += m_data[i] * bi.m_data[j] + carry;
			if (ret.m_data[i + j] >= Base) {
				carry = ret.m_data[i + j] / Base;
				ret.m_data[i + j] %= Base;
			}
			else {
				carry = 0;
			}
		}
		ret.m_data[i + bi.m_size] += carry;
	}
	ret.removeLeadingZeros();
	return ret;
}

BigInt BigInt::operator/(const BigInt& bi) const {
	BigInt ret, carry = 0;
	int l , r , mid;
	for (int i = m_size - 1; i >= 0; i--) {
		carry = carry * Base + m_data[i];
		l = -1;
		r = Base;
		while (l + 1 < r) {
			mid = (l + r) / 2;
			if ((bi * mid).compare(carry) <= 0) {
				l = mid;
			}
			else r = mid;
		}
		ret.m_data[i] = l;
		carry = carry - bi * l;
	}
	ret.m_size = m_size;
	ret.removeLeadingZeros();
	return ret;
}


int main() {
	char s1[10000], s2[10000];
	while (cin >> s1 >> s2) {
		BigInt a(s1), b(s2);
		if (a.compare(b) >= 0)(a - b).print('\n');
		else {
			cout << '-';
			(b - a).print('\n');
		}
	}
	

	return 0;
}

七、总结

高精度运算是一种重要的进阶数据结构技术,它能够处理超出常规数据类型表示范围的极大或极精确数值。通过自定义数据结构(如数组或字符串)和专门的算法实现(如加法、减法、乘法和除法),高精度运算能够在许多领域提供必要的精度和范围支持。掌握高精度运算技术对于提高程序的性能和效率具有重要意义。

结语

当前进阶的数据结构比之前学的初级数据结构要复杂了,希望大家一定要动手敲一遍代码,敲完之后提交到例题里检查一下是否正确,出现bug不用慌张,耐心差错,这样你的水平才能提升。

在这里插入图片描述

希望大家可以一键三连,后续我们一起学习,谢谢大家!!!

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2289639.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式Python版 原型模式

文章目录 前言一、原型模式二、原型模式示例三、原型管理器 前言 GOF设计模式分三大类&#xff1a; 创建型模式&#xff1a;关注对象的创建过程&#xff0c;包括单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、原型模式和建造者模式。结构型模式&#xff1a;关注类和对…

用 JavaScript 打造交互式表格:添加与删除行功能

前言 在网页开发中&#xff0c;创建交互式表格是很常见的。今天我们通过一个示例&#xff0c;来展示如何使用 HTML、CSS 和 JavaScript 实现一个能够动态添加和删除行的表格&#xff0c;并详细解释其中 JavaScript 部分的代码逻辑。 功能展示 初始状态&#xff1a;页面加载后…

Linux02——Linux的基本命令

目录 ls 常用选项及功能 综合示例 注意事项 cd和pwd命令 cd命令 pwd命令 相对路径、绝对路径和特殊路径符 特殊路径符号 mkdir命令 1. 功能与基本用法 2. 示例 3. 语法与参数 4. -p选项 touch-cat-more命令 1. touch命令 2. cat命令 3. more命令 cp-mv-rm命…

服务器虚拟化实战:架构、技术与最佳实践

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 1. 引言 服务器虚拟化是现代 IT 基础设施的重要组成部分&#xff0c;通过虚拟化技术可以提高服务器资源利用率、降低硬件成本&am…

AI大模型开发原理篇-1:语言模型雏形之N-Gram模型

N-Gram模型概念 N-Gram模型是一种基于统计的语言模型&#xff0c;用于预测文本中某个词语的出现概率。它通过分析一个词语序列中前面N-1个词的出现频率来预测下一个词的出现。具体来说&#xff0c;N-Gram模型通过将文本切分为长度为N的词序列来进行建模。 注意&#xff1a;这…

Python从零构建macOS状态栏应用(仿ollama)并集成AI同款流式聊天 API 服务(含打包为独立应用)

在本教程中,我们将一步步构建一个 macOS 状态栏应用程序,并集成一个 Flask 服务器,提供流式响应的 API 服务。 如果你手中正好持有一台 MacBook Pro,又怀揣着搭建 AI 聊天服务的想法,却不知从何处迈出第一步,那么这篇文章绝对是你的及时雨。 最终,我们将实现以下功能: …

leetcode 2080. 区间内查询数字的频率

题目如下 数据范围 示例 这题十分有意思一开始我想对每个子数组排序二分结果超时了。 转换思路&#xff1a;我们可以提前把每个数字出现的位置先记录下来形成集合&#xff0c; 然后拿着left和right利用二分查找看看left和right是不是在集合里然后做一个相减就出答案了。通过…

深入了解 SSRF 漏洞:原理、条件、危害

目录 前言 SSRF 原理 漏洞产生原因 产生条件 使用协议 使用函数 漏洞影响 防御措施 结语 前言 本文将深入剖析 SSRF&#xff08;服务端请求伪造&#xff09;漏洞&#xff0c;从原理、产生原因、条件、影响&#xff0c;到防御措施&#xff0c;为你全面梳理相关知识&am…

11.QT控件:输入类控件

1. Line Edit(单行输入框) QLineEdit表示单行输入框&#xff0c;用来输入一段文本&#xff0c;但是不能换行。 核心属性&#xff1a; 核心信号&#xff1a; 2. Text Edit(多行输入框) QTextEdit表示多行输入框&#xff0c;也是一个富文本 & markdown编辑器。并且能在内容超…

Cesium+Vue3教程(011):打造数字城市

文章目录 Cesium打造数字城市创建项目加载地球设置底图设置摄像头查看具体位置和方向添加纽约建筑模型并设置样式添加纽约建筑模型设置样式划分城市区域并着色地图标记显示与实现实现飞机巡城完整项目下载Cesium打造数字城市 创建项目 使用vite创建vue3项目: pnpm create v…

Windows系统本地部署deepseek 更改目录

本地部署deepseek 无论是mac还是windows系统本地部署deepseek或者其他模型的命令和步骤是一样的。 可以看: 本地部署deepsek 无论是ollama还是部署LLM时候都默认是系统磁盘&#xff0c;对于Windows系统&#xff0c;我们一般不把应用放到系统盘&#xff08;C:&#xff09;而是…

基于Python的药物相互作用预测模型AI构建与优化(下.代码部分)

四、特征工程 4.1 分子描述符计算 分子描述符作为量化分子性质的关键数值,能够从多维度反映药物分子的结构和化学特征,在药物相互作用预测中起着举足轻重的作用。RDKit 库凭借其强大的功能,为我们提供了丰富的分子描述符计算方法,涵盖了多个重要方面的分子性质。 分子量…

[Python学习日记-79] socket 开发中的粘包现象(解决模拟 SSH 远程执行命令代码中的粘包问题)

[Python学习日记-79] socket 开发中的粘包现象&#xff08;解决模拟 SSH 远程执行命令代码中的粘包问题&#xff09; 简介 粘包问题底层原理分析 粘包问题的解决 简介 在Python学习日记-78我们留下了两个问题&#xff0c;一个是服务器端 send() 中使用加号的问题&#xff0c…

origin如何在已经画好的图上修改数据且不改变原图像的画风和格式

例如我现在的.opju文件长这样 现在我换了数据集&#xff0c;我想修改这两个图表里对应的算法里的数据&#xff0c;但是我还想保留这图像现在的形式&#xff0c;可以尝试像下面这样做&#xff1a; 右击第一个图&#xff0c;出现下面&#xff0c;选择Book[sheet1] 选择工作簿 出…

5.3.2 软件设计原则

文章目录 抽象模块化信息隐蔽与独立性衡量 软件设计原则&#xff1a;抽象、模块化、信息隐蔽。 抽象 抽象是抽出事物本质的共同特性。过程抽象是指将一个明确定义功能的操作当作单个实体看待。数据抽象是对数据的类型、操作、取值范围进行定义&#xff0c;然后通过这些操作对数…

【ArcGIS遇上Python】批量提取多波段影像至单个波段

本案例基于ArcGIS python,将landsat影像的7个波段影像数据,批量提取至单个波段。 相关阅读:【ArcGIS微课1000例】0141:提取多波段影像中的单个波段 文章目录 一、数据准备二、效果比对二、python批处理1. 编写python代码2. 运行代码一、数据准备 实验数据及完整的python位…

Spring Security(maven项目) 3.0.2.9版本 --- 改

前言&#xff1a; 通过实践而发现真理&#xff0c;又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识&#xff0c;又从理性认识而能动地指导革命实践&#xff0c;改造主观世界和客观世界。实践、认识、再实践、再认识&#xff0c;这种形式&#xff0c;循环往…

仿真设计|基于51单片机的温度与烟雾报警系统

目录 具体实现功能 设计介绍 51单片机简介 资料内容 仿真实现&#xff08;protues8.7&#xff09; 程序&#xff08;Keil5&#xff09; 全部内容 资料获取 具体实现功能 &#xff08;1&#xff09;LCD1602实时监测及显示温度值和烟雾浓度值&#xff1b; &#xff08;2…

深入剖析 CSRF 漏洞:原理、危害案例与防护

目录 前言 漏洞介绍 漏洞原理 产生条件 产生的危害 靶场练习 post 请求csrf案例 防御措施 验证请求来源 设置 SameSite 属性 双重提交 Cookie 结语 前言 在网络安全领域&#xff0c;各类漏洞层出不穷&#xff0c;时刻威胁着用户的隐私与数据安全。跨站请求伪造&…

buuuctf_秘密文件

题目&#xff1a; 应该是分析流量包了&#xff0c;用wireshark打开 我追踪http流未果&#xff0c;分析下ftp流 追踪流看看 用户 “ctf” 使用密码 “ctf” 登录。 PORT命令用于为后续操作设置数据连接。 LIST命令用于列出 FTP 服务器上目录的内容&#xff0c;但在此日志中未…