题目描述
Csh 被老妈关在家里做分数计算题,但显然他不愿意坐这么多复杂的计算。况且在家门口还有 Xxq 在等着他去一起看电影。为了尽快地能去陪 Xxq 看电影,他把剩下的计算题交给了你,你能帮他解决问题吗?
输入格式
输入一行,为一个分数计算式。
计算式中只包含数字,'','
','
'。其中 '
' 为分数线,分数线左边为分子,右边为分母。输入数据保证不会出现繁分数。如果输入计算式的第一项为正,不会有前缀 '
' 号;若为负,会有前缀 '
' 号。
所有整数均以分数形式出现。
输出格式
输出一行,为最后的计算结果(用最简分数或整数表示)。
保证答案内出现的所有数(如果答案是分数即为分子和分母)均在 位带符号整数的表示范围之内。
样例
样例输入
2/1+1/3-1/4
样例输出
25/12
提示
数据范围及约定
对于所有测试点,输入计算式长度在 以内,分子、分母在
以内。同时保证,直接从前往后直接计算分数的和或者差,然后立刻化简,这么做的中间结果不会超过
的范围。
看一眼发现是处理字符串的题,根据以往的经验,其中必定有鬼。
本蒻蒟为了谨慎起见,还是先读入再处理,虽然有点麻烦。
思路
1. 遍历整个字符串,如果遍历到 '' 就进行下面的操作,否则跳过。
2. 求出分子和分母,然后化为最简分数防止超 范围。
3. 分数加减法运算(通分,计算加减法,化简得数)用两个变量保存得数。
此时的代码实现如下:
#include<bits/stdc++.h>
using namespace std;
char ch[505];
int gcd(int a,int b){
if(a%b==0) return b;
else return gcd(b,a%b);
}
int main()
{
cin.getline(ch,500);
int len=strlen(ch),fz=0,fm=0,oo=0;
for(int i=0;i<len;i++){
if(ch[i]=='/'){
//求分子分母
int k=i-1,left=0,l=1;
while(ch[k]>='0'&&ch[k]<='9'){
left+=int(ch[k]-'0')*l,k--;
l*=10;
}
int q=i+1,right=0,w=1;
while(ch[q]>='0'&&ch[q]<='9') q++;
for(int j=q-1;j>=i+1;j--){
right+=int(ch[j]-'0')*w;
w*=10;
}
//化简原分数
oo=gcd(left,right);
left/=oo,right/=oo;
if(!fz&&!fm){
fz=left,fm=right,s=q;
continue;
}
//通分
int o=fm*right/gcd(fm,right);
left*=o/right,fz*=o/fm;
right=o,fm=o;
//计算加减法
if(ch[i]=='+') fz+=left;
else fz-=left;
//化简
oo=gcd(fz,fm);
fz/=oo,fm/=oo;
}
}
printf("%d/%d",fz,fm);
return 0;
}
非常的简单易懂但连样例都没过。
本蒻蒟经过几分钟折磨人的检查后发现: 次进行加减运算时,用的字符是本该
次运算使用的字符。
比如样例 运行后的得数为
,因为它算的根本是另一个算式:
(
是一个空字符)。
我们可以考虑用两个变量 的不断更新解决这个问题。
d=i=q;
//化简原分数
oo=gcd(left,right);
left/=oo,right/=oo;
if(!fz&&!fm){
fz=left,fm=right,s=q;
continue;
}
//通分
int o=fm*right/gcd(fm,right);
left*=o/right,fz*=o/fm;
right=o,fm=o;
//计算加减法
if(ch[s]=='+') fz+=left;
else fz-=left;
s=d,d=0;
然后成功的拿到了 分,下载了个样例后想给自己一巴掌:输出
??
所以在输出的时候补个判断:
if(fm==1) printf("%d",fz);
else printf("%d/%d",fz,fm);
本以为可以大功告成,结果 分。
再三犹豫后又下了个样例:.输出 ???
于是又又加个特判,这下终于没问题了:
if(fm<0){
fm=-fm;
printf("-");
}
完整代码
#include<bits/stdc++.h>
using namespace std;
char ch[505];
int gcd(int a,int b){ //求最小公因数
if(a%b==0) return b;
else return gcd(b,a%b);
}
int main()
{
cin.getline(ch,500);
int len=strlen(ch),fz=0,fm=0,s=0,d=0,oo=0;
for(int i=0;i<len;i++){
if(ch[i]=='/'){
int k=i-1,left=0,l=1;
while(ch[k]>='0'&&ch[k]<='9'){
left+=int(ch[k]-'0')*l,k--;
l*=10;
}
int q=i+1,right=0,w=1;
while(ch[q]>='0'&&ch[q]<='9') q++;
for(int j=q-1;j>=i+1;j--){
right+=int(ch[j]-'0')*w;
w*=10;
}
d=i=q;
//化简原分数
oo=gcd(left,right);
left/=oo,right/=oo;
if(!fz&&!fm){
fz=left,fm=right,s=q;
continue;
}
//通分
int o=fm*right/gcd(fm,right);
left*=o/right,fz*=o/fm;
right=o,fm=o;
//计算加减法
if(ch[s]=='+') fz+=left;
else fz-=left;
s=d,d=0;
//化简
oo=gcd(fz,fm);
fz/=oo,fm/=oo;
}
}
if(fm<0){
fm=-fm;
printf("-");
}
if(fm==1) printf("%d",fz);
else printf("%d/%d",fz,fm);
return 0;
}
总结
想起一句大佬的话,多判不寄。