3041. 分数的加减运算

CoolCarrot

终于过了!!!
坑死我了!!!最后还是问了老师才知道错哪里[em:07]
字符串可能以“+”开头!我一直以为没有人会没事干开头还放个加号的[em:15]

kingno

很考验耐心…嗯…

Li Dao

写了个分数模板,大家看看。

include

using namespace std;

define LL long long

int T;

struct fraction
{
LL up,down;
LL gcd(LL aa,LL bb)
{
aa=abs(aa);bb=abs(bb);
if(aa<bb) swap(aa,bb);
if(bb==0) return aa;
else return gcd(bb,aa%bb);
}
void reduction()
{
if(up==0)
{
down=1;
return;
}
LL GCD=gcd(up,down);
up/=GCD;down/=GCD;
return;
}
fraction(LL aa,LL bb=1)
{
up=aa;down=bb;
(*this).reduction();
}
void print()
{
if(down==1) printf(“%lld\n”,up);
else printf(“%lld/%lld\n”,up,down);
}
};

fraction operator+(const fraction& aa,const fraction& bb)
{
fraction ret(aa.upbb.down+bb.upaa.down,aa.down*bb.down);
ret.reduction();
return ret;
}

/fraction operator-(const fraction& aa,const fraction& bb)
{
fraction ret(aa.up
bb.down-bb.upaa.down,aa.downbb.down);
ret.reduction();
return ret;
}*/

void solve()
{
int useless;
cin>>useless;
string line;
cin>>line;

int pos=0,ll=line.length();
fraction ans(0);
while(pos<ll)
{
LL a,b;
int symbol=1;
if(line[pos]==’+’) pos++;
if(line[pos]==’-‘) {symbol=-1;pos++;}
LL num=0;
while(pos<ll && isdigit(line[pos]))
{
num=num10+line[pos]-‘0’;
pos++;
}
a=num
symbol;
pos++;

num=0;
while(pos<ll && isdigit(line[pos]))
{
  num=num*10+line[pos]-'0';
  pos++;
}
b=num;

fraction(a,b);
ans=ans+fraction(a,b);

}
ans.print();
return;
}

int main()
{
scanf(“%d”,&T);
for(int step=0;step<T;step++)
{
printf(“case #%d:\n”,step);
solve();
}
return 0;
}

10175102262 LarsPendragon

分数计算和多项式计算是字符串绕不过去的坎。
注意,分母有可能带符号,这时要把负号给分子。
附C代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
long long Abs(long long x)//为了用gcd写了个abs……
{
    if(x<0) return -x;
    else return x;
}
long long gcd(long long a, long long b)
{
    if(Abs(a)<Abs(b)) {a^=b; b^=a; a^=b;}
    if(b==0) return 1;//分子有可能为0要考虑这种情况
    if(a%b) return gcd(b, a%b);
    else return b;
}
int main()
{
    int T, I;
    scanf("%d",&T);
    for(I=0; I<T; I++)
    {
        int n, i, l, cnt=0, sig=1, pos=0;
        long long a[30][2], x;
        char s[85];
        scanf("%d %s",&n,s);
        l=strlen(s);
        for(i=0; i>n; i++) {a[i][0]=0; a[i][1]=0;}
        if(n-1)//分数多于一个
        {
            for(i=0; i<l;)
            {
                if(s[i]=='+') {sig=1; pos=0; if(i) cnt++; i++;}
                else if(s[i]=='-') {sig=-1; pos=0; if(i) cnt++; i++;}
                else if(s[i]=='/') {pos=1; i++;}
                else
                {
                    x=s[i++]-'0';
                    while(s[i]>='0' && s[i]<='9')
                    {
                        x*=10;
                        x+=s[i++]-'0';
                    }
                    a[cnt][pos]=x*sig;
                    sig=1;
                }
            }
            for(i=0; i<cnt; i++)
            {
                a[i+1][0]*=a[i][1];
                a[i][0]*=a[i+1][1];
                a[i+1][1]*=a[i][1];
                a[i+1][0]+=a[i][0];
                x=gcd(a[i+1][0], a[i+1][1]);
                a[i+1][0]/=x;
                a[i+1][1]/=x;
            }
            if(a[i][1]<0) {a[i][1]*=-1; a[i][0]*=-1;}//分母有负号
            if(a[i][0]==0) printf("case #%d:\n0\n",I);//分子为0
            else if(a[i][1]==1) printf("case #%d:\n%lld\n",I,a[i][0]);//分母为1
            else printf("case #%d:\n%lld/%lld\n",I,a[i][0],a[i][1]);//一般情况
        }
        else//只有一个分数
        {
            for(i=0; i<l; i++) if(s[i]=='/') break;
            char m[80];
            strncpy(m, s, i);
            a[0][0]=(long long)atoi(m);//直接转化为整数
            a[0][1]=(long long)atoi(s+i+1);
            x=gcd(a[0][0], a[0][1]);
            if(a[0][1]<0) {a[0][1]*=-1; a[0][0]*=-1;}//分母有负号
            printf("case #%d:\n%lld/%lld\n",I,a[0][0]/x,a[0][1]/x);
        }
    }
    return 0;
}
Kevin_K

Hints:相加时不要写的太粗犷,会哇到怀疑人生的!(用了高精度就是另一回事了)QwQ

DingJR

分数计算有些细节…
1.处理输入:可以用简单的scanf(“%d/%d”,&a,&b),//scanf对于%d是可以处理’+‘号的..
2.计算:两个分数处理得到结果与下一个计算,然后重复上述过程;注意每次得到的分数值都需要”a.约分 b.将符号提到分子”
3.输出:在计算中每次得到的值都完成了提符号和化简。直接查看分母,为1时输出分子,不为1则输出numerator/denominator
4.分数化简代码:

define longabs(a) (a>0? a : (-a))

typedef struct FRAC
{
long long numr;
long long dnmt;
}frac;
frac myfrac[100];

long long gcd(long long a,long long b)
{
return b?gcd(b,a%b):a;
}
void simple(long long a,long long b)
{
long long aa=a,bb=b;
long long bcf=gcd(aa,bb);
(a)=aa/bcf,(b)=bb/bcf;
}
frac FracSimple(frac in)
{
simple(&in.numr,&in.dnmt);
int tag=1;
if(in.numr==0)tag=0;
else if( (( in.numr/longabs(in.numr)) * (in.dnmt/longabs(in.dnmt))) <0) tag=-1;
return (frac){longabs(in.numr)*tag,longabs(in.dnmt) };
}

Master X

又是字符串类的题……难度比那鬼符号方程好多了……
还是c++ string大法好
再来一波毒瘤代码,几乎就是C实现了

include

using namespace std;
long long int gcd(long long int a,long long int b)
{
if(a%b==0) return b;
else return gcd(b,a%b);
}

void solve()
{
int num;
cin>>num;
char s[81];
long long int a[31];
long long int b[31];
scanf(“%s”,s);
int l=strlen(s);
long long int numup=0;
long long int numdown=0;
long long int suan=0;
long long int gcdn=0;
int sqr=1;
int k=0;
for(int i=0;i=‘0’&&s[i]<=‘9’) suan=suan10+s[i]-‘0’;
if(s[i]==’/’&&suan!=0) {
a[k]=suan
sqr;
suan=0;
sqr=1;
//cout<<i<<ends<<k<<ends<<a[k]<<endl;
}
if(s[i]==’-‘){
sqr=-1;
if(suan!=0)
{b[k]=suan;
//cout<<i<<ends<<k<<ends<<b[k]<<endl;
suan=0;
k++;}

    }
    if(s[i]=='+'){
         if(suan!=0)
         {b[k]=suan;
         //cout<<i<<ends<<k<<ends<<b[k]<<endl;
        suan=0;
        k++;}
    }
}
if(suan!=0) b[k]=suan;
numup=a[0],numdown=b[0];
//cout<<k<<endl;
//for(int i=0;i<=k;i++) cout<<a[i]<<ends<<b[i]<<endl;
for(int i=1;i<=k;i++)
    {
        numup=numup*b[i]+numdown*a[i];
        numdown=numdown*b[i];
        gcdn=gcd(numup,numdown);
        numup/=gcdn;
        numdown/=gcdn;
    }
      gcdn=gcd(numup,numdown);
        numup/=gcdn;
        numdown/=gcdn;
        if(numdown<0) numdown*=-1,numup*=-1;
    if(numdown==1) cout<<numup<<endl;

else cout<<numup<<”/”<<numdown<>T;
for(int i=0;i<T;i++)
{
printf(“case #%d:\n”,i);
solve();
}
}

你当前正在回复 博客/题目
存在问题!