PAT 数学问题模板

一、最大公约数与最小公倍数

1.1 最大公因式

//最大公因式
int gcd(int a,int b){
    return !b ? a : gcd(b , a % b);
}

1.2 最小公倍数

//最小公倍数
int lcm(int a,int b){
    int d = gcd(a , b);//d保存a与b的最小公倍数
    return a / d * b;
}

二、素数

2.1 素数判断

bool isPrime(int n){
    if(n<=1) return false;
    for(int i=2; i*i<=n; i++){
        if (n % i == 0) return false;
    }
    return true;
}

2.2 素数表获取

//求解100以内的所有素数
const int maxn = 101;//表长
int prime[maxn], pnum=0; //前者存放所有的素数,后者存放素数个数
void Find_Prime(){
    for(int i = 1; i < maxn; i++){
        //判断是否为素数
        if(isPrime(i) == true){
            prime[num++] = i;
        }
    }
}


三、质因子分解

质因子分解:将一个正整数n写成一个或多个质数的乘积的形式。由于每个质因子出现不止一次,因此定义结构体factor,用来存放质因子及其个数。

struct factor{
    int x,cnt;
}fac[10];//对于int型,数组开到10即可
//质因子分解(分解 int n)

//1、枚举1~sqrt(1.0*n)内所有质数p,判断p是否是n的因子
int n, num=0;
for(int i = 0; prime[i] <= sqrt(1.0 * n) && i < pnum; i++){//prime[i]存放整数n所有的素数, pnum为整数n的质数个数
    if(n % prime[i] == 0){//记录该质因子
        fac[num].x = prime[i];
        fac[num].cnt = 0;
        while(n % prime[i] == 0){
            fac[num].cnt++;
            n/=prime[i];
        }
        num++;
    }
    if(n == 1) break;
}
//2、如果上述结束后,n还是大于1,说明n有且只有一个大于sqrt(1.0*n)的质因子(可能是n本身)(如6=2 x 3, 3大于根号6)
if(n != 1){
    fac[num].x = n;
    fac[num++].cnt = 1;
}

四、分数的四则运算

4.1 分数的表示

struct Fraction{
    int up,down;
};

4.2 分数的化简

Fraction reduction(Fraction result){
    if(result.down<0){//分母小于零
        result.up = -result.up;
        result.down = -result.down;
    }
    if(result.up == 0){
        result.dpwn = 1;
    }else{
        int d = gcd(abs(result.up), abs(result.down));//求分子分母的最大公因式
        result.up /= d;
        result.down /= d;
    }
    return result;
}

4.3 分数加法

Fraction add(Fraction f1, Fraction f2){
    Fraction result;
    result.up = f1.up * f2.down + f1.down * f2.up;
    result.down = f1.down * f2.down;
    return reduction(result);
}

4.4 分数减法

Fraction sub(Fraction f1, Fraction f2){
    Fraction result;
    result.up = f1.up * f2.down - f1.down * f2.up;
    result.down = f1.down * f2.down;
    return reduction(result);
}

4.5 分数乘法

Fraction multi(Fraction f1, Fraction f2){
    Fraction result;
    result.up = f1.up * f2.up;
    result.down = f1.down * f2.down;
    return reduction(result);
}

4.6 分数除法

Fraction divide(Fraction f1, Fraction f2){
    Fraction result;
    result.up = f1.up * f2.down;
    result.down = f1.down * f2.up;
    return reduction(result);
}

4.7 分数的输出

void showResult(Fraction f){
    r = reduction(r);
    if(r.down == 1) printf("%d", r.up); //整数
    else if(abs(r.up) > r.down){//假分数
        printf("%d %d/%d", r.up / r.down, abs(r.up) % r.down, r.down);
    }else{//真分数
        printf("%d/%d", r.up, r.down);
    }
}

五、进制转换

5.1 任意进制转换为十进制

以二进制转换为十进制为例:

基本规则:把二进制数按权展开、相加即得十进制数。

int toDecimal(string s, int radix){    //s是给定的radix进制字符串
	int ans =0;
	for(int i = 0; i < s.size(); i++){
		char t = s[i];
		if(t >= '0' && t <= '9') ans = ans * radix + (t - '0');
		else ans = ans * radix + (t - 'a' + 10);
	}
		return ans;
}

5.2 十进制转换为其他进制

5.2.1 方法一

以十进制转换为二进制为例:

基本规则:十进制数除2取余法,即十进制数除2,余数为权位上的数,得到的商值继续除,直到商为0为止。

string decimalToA(int n, int radix){//n是待转数字(十进制),radix是需转换为的进制
	string ans = "";
	do{
		int t = n % radix;
		if(t >= 0 && t <= 9)	ans += t + '0';//将数字转换为字符
		else ans += t - 10 + 'a';//转换为相应的字母,比如讲十进制的11转换为16进制的b
		n /= radix;
	}while(n != 0);	//使用do{}while()以防止输入为0的情况
	reverse(ans.begin(), ans.end());
	return ans;	
}

5.2.2 方法二

itoa()函数(可以将一个10进制数转换为任意的2-36进制字符串)

用法:charitoa(int value,charstring,int radix);


六、大整数运算

6.1 大整数存储

struct bign{
    int d[1000];
    int len;
    bign(){
        memset(d, 0, sizeof(d));
        len = 0;
    }
};
//按字符串%s读入时,数组高位存储整数低位,需要反转一下,使整数高位存储在数组高位
bign change(char str[]){
    bign a;
    a.len = strlen(str);
    for(int i = 0; i < a.len; i++){
        a.d[i] = str[a.len - 1 - i] - '0';
    }
    return a;
}

6.2 比较大小

int compare(bign a, bign b){//比较a和b大小,a大、相等、a小分别返回1、0、-1
    if(a.len > b.len) return 1;//a大
    else if(a.len < b.len) return -1;//b大
    else{
        for(int i = a.len - 1; i >= 0; i--){//从高位比较
            if(a.d[i] > b.d[i]) return 1;//a大
            else if(a.d[i] < b.d[i]) return -1;
        }
    }
    return 0;//两数相等
}

6.3 高精度加法

bign add(bign a, bign b){
    bign result;
    int carry = 0;//进位
    for(int i = 0; i < a.len || i < b.len; i++){//以较长的一方为界限
        int temp = a.d[i] + b.d[i] + carry;
        result.d[result.len++] = temp % 10;//大数result低位保留大数a、b低位相加的结果temp的个位
        carry = temp / 10;//temp的高位为进位
    }
    if(carry != 0){//加法的进位最多只能有一位,如果最后的进位不为0,直接复制给结果最高位
        result.d[result.len++] = carry;
    }
    return result;
}

6.4 高精度减法

//如果被减数小于减数,需要交换两个变量,输出负号,然后在调用sub()
bign sub(bign a, bign b){
    bign result;
    for(int i = 0; i < a.len || i < b.len; i++){
        if(a.d[i] < b.d[i]){//不够减
            a.d[i+1]--;//向高位借位
            a.d[i] += 10;
        }
        result.d[result.len++] = a.d[i] - b.d[i];//保留当前的减法结果
    }
    while(result.len > 1 && result.[result.len - 1] == 0){
        result.len--;
    }
    return result;
}

6.5 高精度与低精度的乘法

bign multi(bign a, int b){
    bign result;
    int carry = 0;//进位
    for(int i = 0; i < a.len; i++){
        int temp = a.d[i] * b + carry;
        result.d[result.len++] = temp % 10;//个位为该位结果
        carry = temp / 10;//其他位作为进位
    }
    while(carry != 0){//乘法的进位可能不止一位
        result.d[result.len++] = carry % 10;
        carry /= 10;
    }
    return result;
}

6.6 高精度与低精度的除法

bign divide(bign a, int b, int& r){//a为被除数,b为除数,r为余数
    bign result;
    result.len = a.len;//除数位数与商的位数一一对应
    for(int i = a.len - 1; i >= 0; i--){//从高位开始
        r = r * 10 +a.d[i];//和上一位遗留的余数组合
        if(r < b) result.d[i] = 0;//不够除,商该位为0
        else{
            result.d[i] = r / b;
            r = r % b;//更新余数
        }
    }
    while(result.len > 1 && result.d[result.len - 1] == 0){
        c.len--;
    }
    return result;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值