PAT常见数学问题-基本篇

目录

1. 最大公约数与最小公倍数

最大公约数

最小公倍数

 

2.分数的四则运算

分数表示

分数化简

分数的运算

分数的输出

3. 素数问题

4. 质因子分解

 

留个坑,以后更

5. 大整数运算

 

6. 扩展欧几里得算法

 

 

7. 组合数


 

 


1. 最大公约数与最小公倍数


最大公约数

定义:最大公约数是指两个数之间所有公约数最大的那个公约数。

例如:4和6的最大公约数是2;3和9的最大公约数是3。

表示:常用gcd(a,b)表示a和b的最大公约数。

计算方法:常用欧几里得算法,即辗转相除法。

基于定理:设a、b均为正整数,则gcd(a,b)=gcd(b,a%b)

具体实现:写成递归形式。

  1. 递归式:gcd(a,b)=gcd(b,a%b)
  2. 递归边界: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表示分母。

用这个有三个注意事项:

  1. down为非负数,正负号存到up中;
  2. 若分数为0,则规定up=0,down=1;
  3. 分子分母最大公约数为1。

 

分数化简

分数化简要有的操作如下:

  1. 若分母出现负数,则分子分母同时取反;
  2. 若分子up为0,则分母为1;
  3. 若分子分母的最大公约数不是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;
}

 

分数的运算

就按照小学生的操作,一步一步来就行。

加法

\frac{a_1}{b_1}+\frac{a_2}{b_2}=\frac{a_1*b_2+a_2*b_1}{b_1*b_2}

减法

\frac{a_1}{b_1}-\frac{a_2}{b_2}=\frac{a_1*b_2-a_2*b_1}{b_1*b_2}

乘法

\frac{a_1}{b_1}\times \frac{a_2}{b_2}=\frac{a_1*a_2}{b_1*b_2}

除法

\frac{a_1}{b_1} \div \frac{a_2}{b_2}=\frac{a_1*b_2}{a_2*b_1}

分数的输出

分数输出的时候注意以下几点:

  1. 输出前记得化简约分;
  2. 如果分母为1,说明是整数,直接输出分子;
  3. 若分子大于分母则为假分数,可以考虑化简提出整数部分;
  4. 以上三点之外的按正常输出即可

 

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多次取余并更新继续取余,可以统计出当前质数作为因子的数量。

 

留个坑,以后更

5. 大整数运算


 

6. 扩展欧几里得算法


 

 

7. 组合数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值