PAT 1081. Rational Sum (20) 辗转相除法, 分数运算

HAHAH 这种题很成功的1A了,毕竟之前做过类似的


/*************************
题意:
给出一堆分数相加,求最终的结果,表示成n a/b形式
************************/
/***********************
解题思路:
我是每输入一个分数a/A,就计算一下当前的和,即之前的结果b/B 加上现在输入的值
计算方法就是 
先将a/A进行约分(辗转相除法获取最大公约数)
接着求出2个分母的乘积A*B
接着分子等于 a*B+b*A(不在意正负,因为我将所有负数都放在分子中。)
计算好分子分母后,再约分,储存结果
注意以下坑点:
	1、注意0/5, -0/3等情况,尤其是辗转相除法中对于0的处理
	2、 输出最终和时,留意 -8/3 = -2 2/3     
	3、 范围是long long 形式
	4、 先约分,再求和,再约分。
*************************/
/***********************
笔记:
辗转相除法记忆:
	参数是a和b
	让a取大的那个,b取小的那个
	如果a能被b整除, 那结果就是b
	否则 把 a变成a%b,即a换成a除b的余数,继续计算。
	口诀:
	a大,b小
	若不整除, 变a,不变b。
*********************/
#include<iostream>
#include<stdio.h>
#include<string>
#include<vector>
#include<queue>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<stack>
#include<map>
#include<set>
#include<unordered_map>
using namespace std;
#define M 1000
#define INF 0x7ffffff

struct ranum{
	long long  up;
	long long down;
};

ranum num[M];


long long getgcd(long long a, long long b){
	long long t;
	if(a < 0)
		a = (-1) * a;
	if(b < 0)
		b = (-1) * b;
	
	if(a < b){  //让a比b大
		t = b;
		b = a;
		a = t;
	}
	if(a==0 || b==0)
		return 1;

	if(a % b == 0)      //  a能被b整除,那么就是b
		return b;
	else 
		return getgcd(b, a % b);  // 否则,去处理 b和a%b  (a就不管了)
}


int main(){
	int n, i, j, f;
	long long gcd;
	string s;
	ranum lastnum, nownum, ansnum;
	scanf("%d", &n);
	for(i = 0; i < n; i++){
		cin>>s;
		if(s[0] == '-'){
			f = 1;
			j = s.find('/');
			nownum.up = (-1) * atoi(s.substr(1, j-1).c_str());
			nownum.down = atoi(s.substr(j+1).c_str());
		}
		else{
			f = 0;
			j = s.find('/');
			nownum.up = atoi(s.substr(0, j).c_str());
			nownum.down = atoi(s.substr(j+1).c_str());
		}
		//printf("%d  /  %d \n",nownum.up,nownum.down);
		gcd = getgcd(nownum.up, nownum.down);
		nownum.up /= gcd;
		nownum.down /= gcd;
		if(i == 0){
			ansnum = nownum;
			lastnum = nownum;
			continue;
		}
		ansnum.down = lastnum.down * nownum.down;
		ansnum.up = lastnum.up * nownum.down + nownum.up * lastnum.down;
		gcd = getgcd(ansnum.down,ansnum.up);
		ansnum.up /= gcd;
		ansnum.down /= gcd;
		lastnum = ansnum;
	}




	if(abs(ansnum.up) >= ansnum.down){
		printf("%lld",ansnum.up/ansnum.down);
		if(abs(ansnum.up) % ansnum.down !=0 ){
			printf(" %lld/%lld", abs(ansnum.up)%ansnum.down, ansnum.down);
		}
		cout<<endl;
	}
	else{
		if(ansnum.up == 0)
			cout<<"0"<<endl;
		else
			printf("%lld/%lld\n",ansnum.up, ansnum.down);
	}

	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值