《算法笔记》学习记录 Part 2

第五章 数学问题:

5.1 简单数学问题:

PAT-B 1003. 我要通过!(20)  
PAT-B 1019. 数字黑洞 (20)  
PAT-B 1049. 数列的片段和(20)  


5.2 最大公约数与最小公倍数:

    最大公约数的两种写法,运用的原来是欧几里得算法(即辗转相除法)

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

最小公倍数一般用 lcm(a,b) 表示,如果d为a和b的最大公约数,则最小公倍数为ab/d,

为了避免越界,最小公倍数最恰当的写法是a/d*b。由于d是a和b的最大公约数,因此a/d一定可以整除

    

5.3 分数的四则运算:详细代码

PAT-B 1034. 有理数四则运算(20) 


5.4 素数:

Eratosthenes筛法求素数(埃氏筛法)

PAT-B 1007. 素数对猜想 (20) 

PAT-B 1013. 数素数 (20) 

5.5 质因子分解:

      对于一个正整数n来说,如果它存在1和它本身之外的银子,那么一定是在sqrt(n)的左右成对出现。如果它存在[2,n]范围内的质因子,要么这些质因子全部小于等于sqrt(n),要么只存在一个大于sqrt(n)的质因子,而其它质因子全部小于等于sqrt(n)

    思路:

step1:枚举1~sqrt(n)范围内的所有质因子p,判断p是否为n的因子,如果是,就给fac数组中增加质因子p,并初始化个数为0,然后只要p还是n的因子,就让n不断除以p,每次操作令p的个数加1,直到p不再是n的因子为止

struct factor{
	int x,cnt; //x为质因子,cnt为个数
}fac[10];
	if(n%prime[i]==0){	//prime[i]是质数表数组
		fac[num].x = prime[i]; //如果prime[i]是质因子,记录它
		fac[num].cnt = 0;
		while(n%prime[i]==0){	//计算出质因子prime[i]的个数
			fac[num].cnt++;
			n/=prime[i];
		}
		num++;
	} //如果p不是n的因子,直接跳过

step2:如果上面步骤结束后n仍然大于1,说明n有且仅有一个大于sqrt(n)的质因子(也有可能是n本身),这时需要把这个质因子加入fac数组,并令其个数为1

    if(n!=1){
	fac[num].x = n;
	fac[num++].cnt = 1;
    }

5.6 大整数运算

PAT-B 1017. A除以B(20)

5.6.1 大整数的储存

    使用数组,数组中的每一位就代表了存放的每一位,而为了方便随时获取大整数的长度,一般都会定义一个int型变量len来记录其长度,并和d数组成结构体,并在结构体内部加上构造函数

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

输入大整数时,一般都是先用字符串读入,然后把字符串另存为至bign结构体。由于使用char数组进行读入时,整数的高位会变成数组的低位,而整数的低位会变成数组的高位,因此为了让整数在bign中顺位存储,需让字符串倒着赋给d[]数组

bign change(char str[]){
	bign a;
	a.len = strlen(str);
	for(int i=0;i

如果要比较两个bign变量的大小:先判断长度,不相等则长的大;若相等,则从高位到低位进行比较,知道出现某一位不等

5.6.2 大整数的高精度加法

这样写法的条件是两个对象都是非负整数,如果有一方是负的,可以去掉负号,做高精度减法

bign add(bign a,bign b){
	bign c;
	int carry=0;		//carry是进位
	for(int i=0;i
5.6.3 大整数的高精度减法
//默认大减小
bign sub(bign a,bign b){
	bign c;
	for(int i=0;i=1 && c.d[c.len-1]==0){
		c.len--;   	//去除高位的0,同时至少保留一位最低位
	}
	return c;
}
5.6.4 高精度与低精度的除法
bign divide(bign a,int b,int& r){ //高精度除法,r为余数
	bign c;
	c.len = a.len;//被除数的每一位和商的每一位是一一对应的
	for(int i=a.len-1;i>=0;i--){
		r = r*10 + a.d[i];
		if(r=1 && c.d[c.len-1]==0){
		c.len--;		//去除高位0
	}
	return c;
}
5.6.5 高精度与低精度的乘法
bign multi(bign a,bign b){
	bign c;
	int carry = 0;
	for(int i=0;i








你可能感兴趣的:(PATB)