PTA 乙级 1034 有理数四则运算 (20分) C/C++
坑多,坑多
分为几个部分:
加工:将数字化为符合格式要求的形式
化简:使分母始终为正,分子分母化为最简(注意最大公约数为零的情况,否则可能编译无法通过,然后报浮点错误)
求最大公约数:递归利用辗转相除法求最大公约数
加法,减法,除法,乘法运算
辗转相除法
1 long long gcd(long long x, long long y) { 2 long long z = 0; 3 while (x % y) { 4 z = x % y; 5 x = y; 6 y = z; 7 } 8 return z; 9 }
注意:
- 测试点3:
- 用long long类型存储分子分母,题中只是说正确的输出中没有超过整形范围的整数,但乘法可能会出现超过整形范围的整数,以致测试点3报浮点错误
- 记得考虑分子分母绝对值相等的情况,否则会报答案错误
- 还要注意分子分母负负得正(保持分母始终为正数),否则会报答案错误
- 测试点2:注意用空间复杂度小的方法求最大公约数,不可以用枚举法,会超时
C/C++
1 #include<iostream> 2 #include<string> 3 4 using namespace std; 5 6 typedef struct { 7 /*假分数分子*/ 8 long long men; 9 /*真分数分子*/ 10 long long rmen; 11 /*分母*/ 12 long long den; 13 /*真数*/ 14 long long ant; 15 /*最终输出形式*/ 16 string s; 17 }Num; 18 19 long long gcd(long long x, long long y) { //求最大公约数 20 return y == 0 ? x : gcd(y, x % y); 21 } 22 23 int simplify(Num* n) { //化简 24 if (n->den < 0)n->men = -(n->men), n->den = -(n->den); //保持分母始终为正 25 long long rem = gcd(abs(n->men), abs(n->den)); 26 if (rem == 0) return 0; //出现最大公约数为零的情况(没有最大公约数),直接返回 27 n->men /= rem; 28 n->den /= rem; 29 return 0; 30 } 31 32 int process(Num* n) { 33 if (n->den == 0) { //分母为零的情况 34 n->s = "Inf"; 35 return 0; 36 } 37 simplify(n); 38 n->ant = 0; 39 if ((long long)abs(n->men) >= n->den) { //假分数(注意分子分母相等的情况,否则测试点3过不了) 40 if (n->men % n->den == 0) { //可以除尽,化为整数 41 n->ant = n->men / n->den; 42 n->s = to_string(n->ant); 43 } 44 else{ //化为带分数 45 n->ant = n->men / n->den; 46 n->rmen = (long long)abs(n->men) - ((long long)abs(n->ant) * n->den); 47 n->s = to_string(n->ant) + ' ' + to_string(n->rmen) + '/' + to_string(n->den); 48 } 49 } 50 else if (n->men == 0) { //分子为零 51 n->s = "0"; 52 } 53 else { //真分数 54 n->s = to_string(n->men) + '/' + to_string(n->den); 55 } //负数带符号 56 if (n->men < 0 || n->ant < 0)n->s = '(' + n->s + ')'; 57 return 0; 58 } 59 60 void plusnum(Num* x, Num* y, Num* z) { //加法 61 z->den = x->den * y->den; 62 z->men = x->men * y->den + y->men * x->den; 63 process(z); 64 } 65 66 void minusnum(Num* x, Num* y, Num* z) { //减法 67 z->den = x->den * y->den; 68 z->men = x->men * y->den - y->men * x->den; 69 process(z); 70 } 71 72 void multiplynum(Num* x, Num* y, Num* z) { //乘法 73 z->men = x->men * y->men; 74 z->den = x->den * y->den; 75 process(z); 76 } 77 78 void dividenum(Num* x, Num* y, Num* z) { //除法 79 z->men = x->men * y->den; 80 z->den = x->den * y->men; 81 process(z); 82 } 83 84 int main() { 85 Num a, b, ret; 86 scanf_s("%lld/%lld %lld/%lld", &a.men, &a.den, &b.men, &b.den); //vs为scanf_s 87 process(&a); 88 process(&b); 89 plusnum(&a, &b, &ret); 90 cout << a.s << " + " << b.s << " = " << ret.s << endl; 91 minusnum(&a, &b, &ret); 92 cout << a.s << " - " << b.s << " = " << ret.s << endl; 93 multiplynum(&a, &b, &ret); 94 cout << a.s << " * " << b.s << " = " << ret.s << endl; 95 dividenum(&a, &b, &ret); 96 cout << a.s << " / " << b.s << " = " << ret.s << endl; 97 return 0; 98 }
哈哈,还蛮快的
默默地一点点变强,细节决定成败