N个数求和

 

 注意溢出问题,当时想着新生赛,应该不会有溢出的问题,白白贡献了一发wa,还有细节处理没处理好又白白贡献了

一发wa,这道题属于很简单的水题,有良好的代码习惯或者大量的编程一发即AC,我还是太菜了QAQ

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 110;
ll a[N],b[N];
ll c,d;
int n;
ll zhengshu;
ll gcd(ll p, ll q)  //求最大公约数
{
    return q == 0 ? p : gcd(q,p%q);
}
int main()
{
    scanf("%d",&n);
    for(int i = 0; i < n; i++) scanf("%lld/%lld",&a[i],&b[i]);  // 输入分子分母
    int idx = 0;   //分子分母的下标,用于遍历好用
    bool flag = true,numflag = true,fennum = true;   //flag:表示当前值是否大于0 , numflag:表示加的数是否大于0, fennum:表示当前分数是否为0
//flag == false 表示当前值是负数 flag == true 表示当前值是正数
//numflag == true 表示当的分数是正数 numflag == false 表示当前数是负数
//fennum == true 表示计算后的分数是正数 fennun == false 表示计算后的分数是负数 while(n--) // n 个分数 { numflag = true; //判断当前这个分数的正负用 if(a[idx] < 0) a[idx] = abs(a[idx]),numflag = false; //如果当前这个分数是负数,修改标记 if(idx == 0) //第一个数 { if(numflag) // 正数 { c = a[idx]; //分子 d = b[idx]; //分母
//化简 zhengshu = c/d; c = c - zhengshu*d; } else //负数 { c = a[idx]; //分子 d = b[idx]; //分母
//化简 zhengshu = c/d; c = c - zhengshu*d; flag = false; //当前这个值是负数,修改标记 } } else { ll gcdnum = d*(b[idx]/gcd(d,b[idx])); //防止溢出,求最小公倍数,也就是分母 ll oldnum = c*(gcdnum/d); //求的值的分子 ll newnum = a[idx]*(gcdnum/b[idx]); //求的当前分数的分子
//四种情况讨论 if(flag && numflag) //当前值是正数,当前分数是正数 { c = oldnum + newnum; //求新分子 d = gcdnum; //分母
//化简 ll tmp = gcd(c,d); c /= tmp; d /= tmp; ll newzhengshu = c/d; //值的整数部分 zhengshu += newzhengshu; //整数部分 c = c - newzhengshu*d; //分子 } if(flag && !numflag) //当前值是正数,当前分数是负数 { c = oldnum - newnum; //求新分子 if(c < 0) //c < 0表示当前值的分数部分是负数 { fennum = false; //修改标记 c = abs(c); //取绝对值 } d = gcdnum;
//化简 ll tmp = gcd(c,d); c /= tmp; d /= tmp; ll newzhengshu = c/d; c = c - newzhengshu*d; if(fennum) zhengshu += newzhengshu; //如果计算后当前分数部分的值小于0,当前分数的整数部分是负数,反之是正数 else zhengshu -= newzhengshu; if(zhengshu < 0 && !fennum) //当前值整数部分是负数,分数的值也是负数 { flag = false; //修改标记 zhengshu = abs(zhengshu); //取绝对值 } else if(zhengshu >= 0 && !fennum) //当前值的整数是正数,但是分数部分是负数 { zhengshu = zhengshu - 1; //当前值的整数部分减一 c = d - c; //求出当前分子 if(zhengshu >= 0) fennum = true; //当时分数的分子是正数,即当前分数是正数,修改标记 else flag = false; //若当前值的整数部分小于0,修改标记 } } if(!flag && numflag) //当前值是负数,当前分数是是正数 { c = newnum - oldnum; //求分子 if(c >= 0) fennum = true; //当前分数是正数,修改标记 else //若计算后分子是负数,修改标记 { c = abs(c); fennum = false; } //化简 d = gcdnum; ll tmp = gcd(c,d); c /= tmp; d /= tmp; ll newzhengshu = c/d; c = c - newzhengshu*d;
//当前分子是负数,求的新整数部分也是负数,反之是正数 if(fennum) zhengshu = newzhengshu - zhengshu; else zhengshu = newzhengshu + zhengshu; if(zhengshu < 0 && fennum) //当前值还是负数,分子部分是正数 { flag = false; //修改标记 zhengshu = abs(zhengshu); //取绝对值 zhengshu = zhengshu-1; //取了绝对值,当前值是负数,分子是正数,所以整数部分减一 c = d - c; //求分子 fennum = true; //修改标记 } else if(zhengshu < 0 && !fennum) //当前值值的整数部分小于0,分数也小于0 { flag = false; //修改标记 zhengshu = abs(zhengshu); //取绝对值 fennum = true; //修改标记 } else flag = true; //当前整数部分大于0,直接修改标记 } if(!flag && !numflag) //当前值的整数部分小于0,当前分数小于0,一定是个负数 { c = oldnum + newnum; //分子 d = gcdnum; //分母
//化简 ll tmp = gcd(c,d); c /= tmp; d /= tmp; ll newzhengshu = c/d; c = c - newzhengshu*d; zhengshu = zhengshu + newzhengshu; } } idx++; } ll yushu = c%d; //分子分母的余数 if(flag) //现在的值是正数 { if(yushu == 0) cout<<zhengshu<<' '; //只有整数部分 else { if(zhengshu) //整数部分大于0 cout<<zhengshu<<" "<<c<<"/"<<d<<' '; else //没有整数部分 cout<<c<<"/"<<d<<' '; } } else //当前值是负数 { cout<<"-"; //输出负号 if(yushu == 0) //只有整数部分 cout<<zhengshu<<' '; else if(zhengshu) //整数部分非0 cout<<zhengshu<<" "<<c<<"/"<<d<<' '; else //没有整数部分 cout<<c<<"/"<<d<<' '; } return 0; }

  

原文地址:https://www.cnblogs.com/Edviv/p/12253960.html