首页 > 编程语言 >算法笔记(三):数学问题

算法笔记(三):数学问题

时间:2022-11-11 21:37:21浏览次数:30  
标签:int len down ++ 算法 数学 笔记 bign result

最大公约数

辗转相除法

int gcd(int a, int b) {
	if(b == 0) return a;
	return gcd(b, a % b);
}

最小公倍数

根据最大公约数得出最小公倍数

步骤 :

  1. 先求得a与b的最大公约数d
  2. 用a * b / d结果就是要求得的最小公倍数,为了防止数据溢出,也可以写为a / d * b

对分数的处理

#include<bits/stdc++.h>
using namespace std;

int gcd(int a, int b) {
	if(b == 0) return a;
	else gcd(b, a % b);
}

struct Fraction {
	int up, down;	//分子、分母
}p[3];

//对分数进行处理
Fraction reduction(Fraction result) {
	if(result.down == 0) {	//分子为0 
		result.down = 1;
	}
	if(result.down < 0) {
		result.down = -result.down;
		result.up = -result.up;
	}
	else {
		//约分化简 
		int d = gcd(result.up, result.down);	//最大公约数 
		result.up = result.up / d;
		result.down = result.down / d;
	}
	return result;
}

//分数加法 
Fraction add(Fraction f1, Fraction f2, Fraction result) {
	result.up = f1.up * f2.down + f2.up * f1.down;
	result.down = f1.down * f2.down;
	return reduction(result);
}

//分数乘法
Fraction mult(Fraction f1, Fraction f2,Fraction result) {
	
	result.up = f1.up * f2.up;
	result.down = f1.down * f2.down;
	return reduction(result);
}

//输出
void showResult(Fraction res) {
	res = reduction(res);	//化简
	if(res.down == 1) cout<<res.up<<endl;	//分母为1,输出整数
	else cout<<res.up<<"/"<<res.down<<endl;
} 

int main() {
	p[0].up = 10; 
	p[0].down = 4;
	p[1].up = 7;
	p[1].down = 3;
	showResult(p[0]);
	showResult(p[1]);
	showResult(add(p[0], p[1], p[2]));
	showResult(mult(p[0], p[1], p[2]));
	return 0;
}
//输出
5/2
7/3
29/6
35/6

素数

素数即在2~n-1范围内大于1并且只有1和自身两个约数的数,我们可以缩小范围至2~sqrt(n)

普通方法求素数,时间复杂度是O(n * sqrt(n)),如果数据量超过了105则不行了

#include<bits/stdc++.h>
using namespace std;
//求解100以内的素数

int maxn = 101;
int num = 0;
int res[101];
bool p[101];
 
bool isPrime(int n) {
	for(int i = 2; i <= sqrt(n); i++) {
		if(n % i == 0) return false;
	}
	return true;
}

void Build_Prime() {
	
	for(int i = 2; i < maxn; i++) {
		if(isPrime(i)) {
			res[num++] = i;
//			p[i] = true;
		}
	}
}

int main() {
	Build_Prime();	//建表
	for(int i = 0; i < num; i++) {
		cout<<res[i]<<" ";
	} 
	return 0;
}
//输出
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

埃斯筛法

#include<bits/stdc++.h>
using namespace std;
//求解100以内的素数

const int maxn = 101;
int num = 0;
int res[maxn] = {0};
bool p[101];	//初始化都是0,即false

void Build_Prime() {
	for(int i = 2; i < maxn; i++) {
		if(p[i] == 0) {
			res[num++] = i;	//存素数 
//			p[i] = true;
//			4 6 8 10...
//			6 9 12 15...
//			8 12 16...
			for(int j = i * i; j < maxn; j += i) {
				p[j] = 1;	//存判断条件 
			}
		}
	}
}

int main() {
	Build_Prime();	//建表
	for(int i = 0; i < num; i++) {
		cout<<res[i]<<" ";
	}
	return 0;
}

质因子分解

  1. 先获取n以内的素数表,再定义一个结构体
struct factor {
    int x;	//因子
    int cnt;	//该因子个数
};
  1. 对sqrt(n)以内的数进行判断能否对n取余,如果能就代表是n的因子,
  2. 不断对这个数取余并操作,得到这个因子的个数,
  3. 操作到最后得到的n如果是1,则取余完成,如果不是1,则n是一个素数,只有两个因子,一个是1,另一个是它本身

大整数四则运算

对于一个大整数,应该将其存入数组中,再进行操作

#include<bits/stdc++.h>
using namespace std;

struct bign {
	int d[1000];
	int len;
	bign() {
		memset(d, 0, sizeof(d));
		len = 0;
	}
};

//将整数转化为数组 
bign change(char ch[] ) {
	bign a;
	a.len = strlen(ch);
	for(int i = 0; i < a.len; i++) {
		a.d[i] = ch[a.len - i - 1] - '0';
	}
	return a;
}
//加法 
bign add(bign a, bign b) {
	bign c;
	int carry = 0;	//进位 
	for(int i = 0; i < a.len || i < b.len; i++) {
		int temp = a.d[i] + b.d[i] + carry;
		c.d[c.len++] = temp % 10;
		carry = temp / 10;
	}
	if(carry != 0) {	//当两个数相加到最高位时,可能会进一位 
		c.d[c.len++] = carry;
	}
	return c; 
}

//减法
bign sub(bign a, bign b) {
	bign c;
	for(int i = 0; i < a.len || i < b.len; i++) {
		if(a.d[i] < b.d[i]) {
			a.d[i + 1]--;	//高位借1 
			a.d[i] += 10;
		}
		c.d[c.len++] = a.d[i] - b.d[i];
	}
	while(c.len - 1 >= 1 && c.d[c.len - 1] == 0) {	//当最高位是0时去掉 
		c.len--;
	} 
	return c;
} 

//乘法,与学过的乘法不同 
bign mult(bign a, int b) {
	bign c;
	int carry = 0;
	for(int i = 0; i < a.len; i++) {
		int temp = a.d[i] * b + carry;
		c.d[c.len++] = temp % 10;
		carry = temp / 10;
	}
	while(carry != 0) {	//乘法进位可能不止一位 
		c.d[c.len++] = carry % 10;
		carry /= 10; #
	}
	return c;
}

//除法
int r = 0;
bign divide(bign a, int b) {	//r为余,初始应为0 
	bign c;
	
	c.len = a.len;	//被除数和商长度一一对应,相等 
	for(int i = a.len - 1; i >= 0; i--) {	//从高位开始 
		r = r * 10 + a.d[i];
		if(r < b) c.d[i] = 0;
		else {
			c.d[i] = r / b;
			r = r % b;
		}
	}
	//去掉高位的0 
	while(c.len - 1 >= 1 && c.d[c.len - 1] == 0) {
		c.len--;
	}
	return c;
}
 
void print(bign a) {
	for(int i = a.len - 1; i >= 0; i--) {
		printf("%d", a.d[i]);
	} 
}

int main() {
	char str1[1000], str2[1000];
	cin>>str1>>str2;
	bign a = change(str1);
	bign b = change(str2);
	print(add(a, b));
	cout<<endl;
	print(sub(a, b));
	cout<<endl;
	print(divide(a, 4));
	cout<<endl;
	cout<<"余数:"<<r<<endl; 
	print(mult(a, 11));
	return 0;
}

高精阶乘

n!

#include<bits/stdc++.h>
using namespace std;

const int N = 1e4 + 10;
int a[N];
int index = 1;	//表示最大位所在的位置,初始为个位,在a[1]处 

int main() {
	int n;
	cin >> n;
	a[1] = 1;
	for (int i = 1; i <= n; i++) {
		int t = 0;	//进位的数 
		for (int j = 1; j <= index; j++) {
			a[j] = a[j] * i + t;
			t = a[j] / 10;
			a[j] = a[j] % 10;
		}
		while (t > 0) {	//进位 
			a[index + 1] = t % 10;
			t /= 10;
			index++;
		}
	}
	for (int i = index; i >= 1; i--) {
		cout << a[i];
	}
	return 0;
}

高精加法

a + b

#include<bits/stdc++.h>
using namespace std;

const int N = 1e4 + 10;
char a[N], b[N];
int p[N], q[N], res[N];

int main() {
	cin >> a >> b;
	int la = strlen(a);
	int lb = strlen(b);
	for (int i = 0; i < la; i++) {
		p[i] = a[la - i - 1] - '0';
	}
	for (int i = 0; i < lb; i++) {
		q[i] = b[lb - i - 1] - '0';
	}
	int len = max(la, lb);
	int t = 0;	//进位的数 
	for (int i = 0; i < len; i++) {
		res[i] = p[i] + q[i] + t;
		t = res[i] / 10;
		res[i] = res[i] % 10;
	}
	if (t == 1) cout << 1;
	for (int i = len - 1; i >= 0; i--) {
		cout << res[i];
	}
	return 0;
}

标签:int,len,down,++,算法,数学,笔记,bign,result
From: https://www.cnblogs.com/RCLiu/p/16882061.html

相关文章

  • 算法笔记(二):知识点补充
    万能头文件#include<bits/stdc++.h>数组最大范围int型一维数组:小于4e8,即4亿int型二维数组:小于2e4,即2万数据类型范围int和long都是用32位来存储最大值和最小值分......
  • Floyd算法的关键点
    Floyd算法的代码很简单,就是三个for这个算法最重要的地方就是中转点的枚举for(intk=1;k<=n;k++)for(inti=1;i<=n;i++)for(intj=1;j<=n;j++)g[i][j]=max(g[i][j],g[i......
  • .net Elasticsearch 学习入门笔记
    .netElasticsearch(es)学习入门笔记及简要总结。一.es安装相关1.elasticsearch安装运行http://localhost:9200/2.head插件3.bigdesk插件安装(安装细节百度:windows......
  • 旋转门数据压缩算法在PostgreSQL中的实现 - 流式压缩在物联网、监控、传感器等场景的
      背景在物联网、监控、传感器、金融等应用领域,数据在时间维度上流式的产生,而且数据量非常庞大。例如我们经常看到的性能监控视图,就是很多点在时间维度上描绘的曲线......
  • C++学习笔记
    C++学习笔记!这是刚开始写的文件,后来发现太大不合适就开始分开写了#include<iostream>#include<string>//c++风格字符串头文价//下面是定义宏常量:宏常量一旦定下,下文就......
  • Latex数学公式学习
    要想博客写的更详细,更好,那么具体详细的数学推导这一部分是少不了的,不仅要好看还要方便输入那些更为复杂的符号,因此学习Latex就是必不可少的啦,说不定过几天就要用嘞!本......
  • 回溯算法dfs: lc46全排列 lc47全排列ll
    result=[] defbacktrack(路径,选择列表):if满足结束条件:result.add(路径)returnfor选择in选择列表:做选择backtrack(路径,选择列表)撤销选择 46全......
  • VueRouter笔记 - 路由守卫
    路由守卫目录路由守卫1.路由守卫简介2.全局前置守卫3.全局后置路由守卫4.独享路由守卫5.组件内路由守卫1.路由守卫简介路由守卫主要用来通过跳转或取消的方式守......
  • 20201322学习笔记11
    第十三章TCP/IP和网络编程概述本章论述了TCP/IP和网络编程,分为两个部分。第一部分论述了TCP/IP协议及其应用,具体包括TCP/IP栈、IP地址、主机名、DNS、IP数据包和路由器;......
  • 实验三:朴素贝叶斯算法实验
    【实验目的】理解朴素贝叶斯算法原理,掌握朴素贝叶斯算法框架。【实验内容】针对下表中的数据,编写python程序实现朴素贝叶斯算法(不使用sklearn包),对输入数据进行预测;熟悉s......