目录
1. 最大公约数与最小公倍数
最大公约数
定义:最大公约数是指两个数之间所有公约数最大的那个公约数。
例如:4和6的最大公约数是2;3和9的最大公约数是3。
表示:常用gcd(a,b)表示a和b的最大公约数。
计算方法:常用欧几里得算法,即辗转相除法。
基于定理:设a、b均为正整数,则gcd(a,b)=gcd(b,a%b)。
具体实现:写成递归形式。
- 递归式:gcd(a,b)=gcd(b,a%b)
- 递归边界:gcd(a,0)=a
(注意:不用考虑a和b的大小顺序问题,因为在递归的时候,如果a<b,则经过一次gcd操作后带入下一轮的操作是gcd(b,a),函数本身会完成对调操作。
int gcd(int a,int b) { if(b==0) return a; else return gcd(b,a%b); } //或者,下面简洁写法 int gcd(int a,int b) { return !b?a:gcb(b,a%b); }
最小公倍数
定义:两个正整数的所有公倍数中最小的那个公倍数。
例如:4和6的最小公倍数是12;3和9的最小公倍数是9。
表示:常用lcm(a,b)表示a和b的最小公倍数。
计算方法:在求最大公约数的基础上,两数的乘积除以最大公约数,即为最小公倍数。
基于定理:设a、b均为正整数,其最大公倍数为d=gcb(a,b);因此他们的最小公倍数为(a*b)/d=(a*b)/gcd(a,b)。
具体实现:先用gcd函数求最大公倍数d,然后两数相乘再除d,为了防止溢出,采用先除再乘(因为d是公约数,所有相除定为整数)。
int gcd(int a,int b) { return !b?a:gcb(b,a%b); } int lcm(int a,int b) { int d=gec(a,b); return a/d*b; }
2.分数的四则运算
(这个分数的运算,有一个很好的例子,具体可见PAT的乙级题目1034 有理数四则运算 。)
分数表示
可以用结构体来存储分数
struct Fraction
{
int up , down;
};
up代表分子,down表示分母。
用这个有三个注意事项:
- down为非负数,正负号存到up中;
- 若分数为0,则规定up=0,down=1;
- 分子分母最大公约数为1。
分数化简
分数化简要有的操作如下:
- 若分母出现负数,则分子分母同时取反;
- 若分子up为0,则分母为1;
- 若分子分母的最大公约数不是1,那么要进行约分,也就是分子分母同除最大公约数。
化简程序如下:
Fraction reducation(Fraction result)
{
if(result.down<0)
{
result.up= -result.up;
result.down= -result.down;
}
if(result.up==0)
{
result.down=1;
}
else{
int d=gcd(abs(result.up),abs(result.down));
result.up /= d;
result.down /= d;
}
return result;
}
分数的运算
就按照小学生的操作,一步一步来就行。
加法
减法
乘法
除法
分数的输出
分数输出的时候注意以下几点:
- 输出前记得化简约分;
- 如果分母为1,说明是整数,直接输出分子;
- 若分子大于分母则为假分数,可以考虑化简提出整数部分;
- 以上三点之外的按正常输出即可
3. 素数问题
判断n是否是素数的时候,对于除数的选择只需要只需要验证一部分,对n开平方向下取整,验证到这里就行了。
(至于为什么时开方,是因为两数是乘积运算,倘若相加则为除法。)
bool judge(int n)
{
if(n<=1)return false;
int sqr=(int)sqrt(1.0*n);
for(int i=2;i<=sqr;i++)
if(n%i==0)return false;
return true;
}
在实际的操作在,常常先将素数打表存入,然后方便后期调用查找。
打表操作可以借助vector数组来动态存储,如下:
vector<int> vi;
for(j=2;j<200001;j++)
if(judge(j))vi.push_back(j);
4. 质因子分解
由于一个数的同一个质因子可以有多个,所有在其结构体中加入对其数量的统计
struct factor{
int x , count;
}fac[10];
//fac[i]存的是第i个质因子的内容和计数
求解质因子的思路和质数的思路大体一致,最多遍历到它的开方数为止,如果还有大于开方的质因子,说明是它本身。
每遍历到一个数,用while多次取余并更新继续取余,可以统计出当前质数作为因子的数量。