熱門文章

2025年7月25日 星期五

ZeroJudge 解題筆記:b538. 分數運算-2

作者:王一哲
日期:2025年7月25日


ZeroJudge 題目連結:b538. 分數運算-2

解題想法


這題比b537. 分數運算-1簡單很多,只要按照分數運算的規則,分別寫出加、減、乘、除的計算方式,再用 gcd 將分子、分母約分。輸出時分別三種:0、整除、分數,如果分母是負的,負號要加在分子的前面。

Python 程式碼


使用時間約為 19 ms,記憶體約為 3.4 MB,通過測試。
import sys, math

def fac_cal(a, b, c, d, op):
    num, den = 1, 1  # 計算結果的分子、分母
    if op == "+":  # a/b + c/d = (a*d + c*b) / (b*d)
        num = a*d + c*b 
        den = b*d
    elif op == "-":  # a/b - c/d = (a*d - c*b) / (b*d)
        num = a*d - c*b
        den = b*d
    elif op == "*":  # a/b * c/d = (a*c) / (b*d)
        num = a*c
        den = b*d
    else:  # a/b / c/d = a/b * d/c = (a*d) / (b*c)
        num = a*d
        den = b*c
    if den < 0:  # 如果分母小於 0,將分子、分母的正負號都反過來
       num = -num; den = -den
    g = math.gcd(num, den)  # 取分子、分母最大公因數約分
    num //= g; den //= g
    if num == 0: return "0\n"  # 分子為 0,回傳 0
    elif num%den == 0: return f"{num:d}\n"  # 可以整除,回傳分子
    else: return f"{num:d}/{den:d}\n"  # 不能整除

result = []
lines = sys.stdin.readlines()
for line in lines:
    arr = line.split()
    a, b, c, d = map(int, arr[:4])  # 分割出前 4 個數字
    op = arr[-1]  # 運算符號
    result.append(fac_cal(a, b, c, d, op))
sys.stdout.write("".join(result))

使用時間約為 32 ms,記憶體約為 4.5 MB,通過測試。
import sys, fractions

result = []
lines = sys.stdin.readlines()
for line in lines:
    arr = line.split()
    a, b, c, d = map(int, arr[:4])  # 分割出前 4 個數字
    op = arr[-1]  # 運算符號
    x = fractions.Fraction(a, b)
    y = fractions.Fraction(c, d)
    if op == '+': z = x + y
    elif op == '-': z = x - y
    elif op == '*': z = x * y
    else: z = x / y
    result.append(f"{z}\n")
sys.stdout.write("".join(result))


C++ 程式碼


使用時間約為 5 ms,記憶體約為 88 kB,通過測試。
#include <cstdio>
#include <algorithm>
using namespace std;

void fac_cal(int a, int b, int c, int d, char op) {
    int num, den;  // 計算結果的分子、分母
    if (op == '+') {  // a/b + c/d = (a*d + c*b) / (b*d)
        num = a*d + c*b;
        den = b*d;
    } else if (op == '-') {  // a/b - c/d = (a*d - c*b) / (b*d)
        num = a*d - c*b;
        den = b*d;
    } else if (op == '*') {  // a/b * c/d = (a*c) / (b*d)
        num = a*c;
        den = b*d;
    } else {  // a/b / c/d = a/b * d/c = (a*d) / (b*c)
        num = a*d;
        den = b*c;
    }
    int g = __gcd(num, den);  // 取分子、分母最大公因數約分,這兩行要在第 22 ~ 24 行之前
    num /= g; den /= g;
    if (den < 0) {  // 如果分母小於 0,將分子、分母的正負號都反過來
       num = -num; den = -den;
    }
    if (num == 0) {  // 分子為 0,印出 0
        puts("0");
    } else if (den == 1) {  // 可以整除,印出分子
        printf("%d\n", num);    
    } else {  // 不能整除
        printf("%d/%d\n", num, den);
    }
}

int main() {
    int a, b, c, d; // 前 4 個整數
    char op;  // 運算符號
    while(scanf("%d %d %d %d %c", &a, &b, &c, &d, &op) != EOF) {
        fac_cal(a, b, c, d, op);
    }
    return 0;
}

使用時間約為 2 ms,記憶體約為 100 kB,通過測試。
#include <cstdio>
#include <algorithm>
using namespace std;

void fac_cal(int a, int b, int c, int d, char op) {
    int num, den;  // 計算結果的分子、分母
    switch (op) {
        case '+':  // a/b + c/d = (a*d + c*b) / (b*d)
            num = a*d + c*b;
            den = b*d;
            break;
        case '-':  // a/b - c/d = (a*d - c*b) / (b*d)
            num = a*d - c*b;
            den = b*d;
            break;
        case '*':  // a/b * c/d = (a*c) / (b*d)
            num = a*c;
            den = b*d;
            break;
        default:  // a/b / c/d = a/b * d/c = (a*d) / (b*c)
            num = a*d;
            den = b*c;
    }
    int g = __gcd(num, den);  // 取分子、分母最大公因數約分,這兩行要在第 22 ~ 24 行之前
    num /= g; den /= g;
    if (den < 0) {  // 如果分母小於 0,將分子、分母的正負號都反過來
       num = -num; den = -den;
    }
    if (num == 0) {  // 分子為 0,印出 0
        puts("0");
    } else if (den == 1) {  // 可以整除,印出分子
        printf("%d\n", num);    
    } else {  // 不能整除
        printf("%d/%d\n", num, den);
    }
}

int main() {
    int a, b, c, d; // 前 4 個整數
    char op;  // 運算符號
    while(scanf("%d %d %d %d %c", &a, &b, &c, &d, &op) != EOF) {
        fac_cal(a, b, c, d, op);
    }
    return 0;
}


沒有留言:

張貼留言