1. 程式人生 > >PAT 分數運算 (大模擬) - 詳細題解

PAT 分數運算 (大模擬) - 詳細題解

毫無疑問, 這是一道純粹的模擬題, 沒有任何地方有規律可循, 完全模擬數學運算就好了

模擬題一般情況都很複雜, 需要分類討論, 幸好我們在初高中都已經熟練了分數運算, 這裡總結一下, 尤其要把計算機同數學不一樣的地方著重處理

(1)加減法

     分母相同, 直接加減            //計算機裡整數/整數同數學不同, 可能丟數

     分母不同, 先通分, 再加減, 執行(3)

(2)乘除法

     乘法直接相乘, 執行(3)

     除法先取倒數後相乘, 執行(3)

(3)約分

     a, b分別除以gcd(a, b), 這裡尤其要注意負數的情況, 先取絕對值再求

還是WA了好多次, 看來模擬還是要多練練

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef  long long LL;

char op;
int a1, b1, a2, b2;
int a, b; //給出a1/b1 a2/b2, 求a/b

int gcd(int m, int n)
{ //返回m, n最大公約數
    if(m < n) swap(m, n);
    int tmp = m%n;
    while(tmp > 0){
        m = n, n = tmp;
        tmp = m%n;
    }
    return n;
}
int lcm(int m, int n)
{ //返回m, n最小公倍數
    return m*n/gcd(m,n);
}

void reducte()
{ //約分a, b
    int t = gcd(fabs(a), fabs(b)); //防止負數
    a /= t, b /= t;
}
void multiply()
{
    if(op=='/'){
        if(a2 < 0)
            b2 -= 2*b2, a2 += 2*a2; //負數考慮負號問題
        swap(a2, b2);
    }
    a = a1*a2, b = b1*b2;
    reducte();
}
void add()
{ //相加或相減
    if(b1 != b2){
        b = lcm(b1, b2);
        if(op == '+')
            a = b/b1*a1 + b/b2*a2; //通分
        else if(op == '-')
            a = b/b1*a1 - b/b2*a2;
        reducte();
    }
    else{ //墳墓相同無須通分
        if(op=='+')
            a = a1+a2;
        else if(op=='-')
            a = a1-a2;
        b = b1;
        reducte();
    }
}

int main()
{
    while(scanf("%d/%d %d/%d %c",&a1,&b1,&a2,&b2,&op) != EOF){
        if(op == '+' || op == '-')
            add();
        else if(op == '*' || op == '/')
            multiply();
        printf("%d/%d\n",a,b);
    }
	return 0;
}