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<<'\n'; //只有整数部分
else
{
if(zhengshu) //整数部分大于0
cout<<zhengshu<<" "<<c<<"/"<<d<<'\n';
else //没有整数部分
cout<<c<<"/"<<d<<'\n';
}
}
else //当前值是负数
{
cout<<"-"; //输出负号
if(yushu == 0) //只有整数部分
cout<<zhengshu<<'\n';
else if(zhengshu) //整数部分非0
cout<<zhengshu<<" "<<c<<"/"<<d<<'\n';
else //没有整数部分
cout<<c<<"/"<<d<<'\n';
}
return 0;
}
永远年轻 永远热泪盈眶!

浙公网安备 33010602011771号