1. 起先,一个用例浮点错误,但是在进入出发之前,明明已经有判断被除数的分子是否为0,另有一个答案错误,但是和书上代码对照,没有区别。题目中说:“题目保证正确的输出中没有超过整型范围的整数”。注意了,这里输出的是化简后,那么化简之前呢?很有可能超过int范围!所以通过搜索键,把用到的int一律换成long long。
2. 这道题就是为书上的讲解思路量身定制的(或者说书上是为这道题量身定制的),有以下注意点
(1)用结构体来表示有理数(整数是分母为1的有理数),且保证要负也是分子为负,如果分子为0,则分母为1,约分函数reduction不仅仅做约分这一件事,而且负责纠正不符合格式的。约分的时候要注意的是,求最大公约数函数gcd默认接收的是整数,而分数的分子也许为负,因此要用它的绝对值。
fraction reduction(fraction r){if(r.mom<0){//分母为负数,让其成为规定的分数的模样 r.son = -r.son;r.mom = -r.mom;}if(r.son == 0){r.mom = 1;}else{LL m = gcd(abs(r.son),r.mom);//最大公因子:取绝对值很容易丢 //约分r.son /= m;r.mom /= m; }return r;
}
(2) 由于月份的时候会用到求最大公约数,所以最大公约数的函数,显然要会写,注意参数和返回值的类型
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);
}
(3) 对于输出函数printf,注意要首先对传入的有理数进行约分,然后分为整数、假分数、真分数三种类型输出(此题还要额外判断正负决定是否加括号)。其中稍微麻烦一些的是假分数需要考虑负数的情况。化成整数+真分数的形式后,真分数的分子要用绝对值。
void print(fraction r){//输出化简后的分数r = reduction(r);if(r.mom == 1){//整数(当然包括0)if(r.son<0)printf("(%lld)",r.son);//如果是负数 else printf("%lld",r.son);}else if(abs(r.son)>r.mom){//假分数 if(r.son<0)printf("(%lld %lld/%lld)",r.son/r.mom,abs(r.son)%r.mom,r.mom);else printf("%lld %lld/%lld",r.son/r.mom,abs(r.son)%r.mom,r.mom); }else{//真分数 if(r.son<0)printf("(%lld/%lld)",r.son,r.mom);else printf("%lld/%lld",r.son,r.mom);}
}
(4) 此外加减乘除的函数各自就看数学基础了,对于除法可以不在函数里面判断除数是否为0,可以在调用之前判断,要是为0就不去调用。
AC代码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<bits/stdc++.h>
#include<stdlib.h>
#include<time.h>using namespace std;
typedef long long LL;const int maxn = 100010;
const int MOD = 1000000007;
const int INF = 1000000000;//INF:下确界
const LL SUP = (1LL<<63)-1;//SUP:上确界
const double eps = 1e-5;struct fraction{LL son;LL mom;
};LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);
}fraction reduction(fraction r){if(r.mom<0){//分母为负数,让其成为规定的分数的模样 r.son = -r.son;r.mom = -r.mom;}if(r.son == 0){r.mom = 1;}else{LL m = gcd(abs(r.son),r.mom);//最大公因子:取绝对值很容易丢 //约分r.son /= m;r.mom /= m; }return r;
}void print(fraction r){//输出化简后的分数r = reduction(r);if(r.mom == 1){//整数(当然包括0)if(r.son<0)printf("(%lld)",r.son);//如果是负数 else printf("%lld",r.son);}else if(abs(r.son)>r.mom){//假分数 if(r.son<0)printf("(%lld %lld/%lld)",r.son/r.mom,abs(r.son)%r.mom,r.mom);else printf("%lld %lld/%lld",r.son/r.mom,abs(r.son)%r.mom,r.mom); }else{//真分数 if(r.son<0)printf("(%lld/%lld)",r.son,r.mom);else printf("%lld/%lld",r.son,r.mom);}
}fraction add(fraction r1,fraction r2){fraction r3;r3.son = r1.son*r2.mom + r2.son*r1.mom;r3.mom = r1.mom*r2.mom;return reduction(r3);
}fraction minu(fraction r1,fraction r2){fraction r3;r3.son = r1.son*r2.mom - r2.son*r1.mom;r3.mom = r1.mom*r2.mom;return reduction(r3);
}fraction multi(fraction r1,fraction r2){fraction r3;r3.son = r1.son*r2.son;r3.mom = r1.mom*r2.mom;return reduction(r3);
}fraction divide(fraction r1,fraction r2){//不在函数里面做除数是否为0的合法校验 fraction r3;r3.son = r1.son*r2.mom;r3.mom = r1.mom*r2.son;return reduction(r3);
}int main(){fraction r1,r2;scanf("%lld/%lld %lld/%lld",&r1.son,&r1.mom,&r2.son,&r2.mom);print(r1);printf(" + ");print(r2);printf(" = ");print(add(r1,r2));printf("\n");print(r1);printf(" - ");print(r2);printf(" = ");print(minu(r1,r2));printf("\n");print(r1);printf(" * ");print(r2);printf(" = ");print(multi(r1,r2));printf("\n");print(r1);printf(" / ");print(r2);printf(" = ");if(r2.son!=0)print(divide(r1,r2));else printf("Inf");printf("\n");return 0;
}