暴力+輾轉相除法——N個數求和

題目來源

PTA 團體程序設計天梯賽-練習集 L1-009 N個數求和 (20分)

https://pintia.cn/problem-sets/994805046380707840/problems/994805133597065216

 

題目描述

本題的要求很簡單,就是求N個數字的和。麻煩的是,這些數字是以有理數分子/分母的形式給出的,你輸出的和也必須是有理數的形式。

輸入格式:

輸入第一行給出一個正整數N(≤100)。隨後一行按格式a1/b1 a2/b2 ...給出N個有理數。題目保證所有分子和分母都在長整型範圍內。另外,負數的符號一定出現在分子前面。

輸出格式:

輸出上述數字和的最簡形式 —— 即將結果寫成整數部分 分數部分,其中分數部分寫成分子/分母,要求分子小於分母,且它們沒有公因子。如果結果的整數部分爲0,則只輸出分數部分。

輸入樣例1:

5
2/5 4/15 1/30 -2/60 8/3

輸出樣例1:

3 1/3

輸入樣例2:

2
4/3 2/3

輸出樣例2:

2

輸入樣例3:

3
1/3 -1/6 1/8

輸出樣例3:

7/24

 

思路

從題目“分子/分母”的輸入形式可以看出我們不能採用scanf和cin直接輸輸入值 而要採用字符輸入再轉換爲數值

計算過程中判斷好符號 暴力通分直接加減即可

防止通分過程超出長整型範圍 最好每一步結果都約分

我最開始暴力約分來着 發現會超時 就用歐幾里得算法了 不麻煩也不會超時

輸出時注意題目要求的形式 想仔細一點每種條件怎麼輸出即可

 

代碼

#include <cstdio>
using namespace std;
int n,o=1,oo; char x=1; //o-結果是否爲非負數 oo-當前輸入的有理數是否爲非負數
long long p,q,f=0,g=1,c;
inline long long read(); //快讀 由於分子分母間有‘/’分隔且分母一定是正數 標準快讀模板即可完成
inline int yue(long long a,long long b);//求a和b的最大公約數
int main()
{
	scanf("%d",&n); 
	for(int i=1;i<=n;i++)
	{
		while(!(x>=48&&x<=57)&&x!='-')
			x=getchar();
		if(x=='-') oo=0;
		else	oo=1; //判斷當前輸入的有理數是否爲非負數
		p=read();
		q=read(); //以“|p/q|”形式讀入當前有理數
		p*=g;
		f*=q;
		g*=q; //暴力通分 本題數據範圍內沒有超出長整型
		if((o&&oo)||(!o&&!oo)) //如果結果和當前輸入有理數同號 只要分子絕對值部分相加即可
			f+=p;
		else if(o&&!oo) //如果結果爲正 當前輸入有理數爲負 則需要比較結果與當前輸入有理數的大小來確定此次運算後結果的符號 
		{
			if(f>=p) //當前結果大於當前輸入有理數的絕對值 結果仍爲正數 以下同理 
				f-=p;
			else
				o=0,f=p-f;
		}
		else if(!o&&oo)
		{
			if(f>=p)
				o=1,f-=p;
			else
				f=p-f;
		}
		int u=yue(f,g); //u爲f和g的最大公約數
		f/=u;
		g/=u; //約分
	}
	if(o==0) printf("-"); //如果結果是負數 輸出負號
	if(f==0)	printf("0"); //如果結果是0 輸出0
	else if(f%g==0)	printf("%lld",f/g); //如果結果可以約分爲整數
	else if(g%f==0) printf("1/%lld",g/f);//如果結果可以約分爲“1/x”形式
	else if(f>g) //如果結果的分子大於分母 即結果爲假分數 需要轉化爲帶分數
	{
		printf("%lld ",f/g); //整數部分
		f%=g;
		printf("%lld/%lld",f,g); //分數部分
	}
	else
		printf("%lld/%lld",f,g); //如果結果爲真分數
	return 0;
}
inline int yue(long long a,long long b) //歐幾里得算法 親測暴力約分會超時
{
	if(a>b) c=a,a=b,b=c; 
	while(a!=0) //
	{
		while(b>=a) //標準%運算比較慢 直接減
			b-=a;
		c=a,a=b,b=c;
	}
	return b;
}
inline long long read()
{
	long long s=0;
	while(!(x>=48&&x<=57))
		x=getchar();
	while(x>=48&&x<=57)
		s*=10,s+=x-48,x=getchar();
	return s;
}

 

吐槽

很少見到PTA這樣AC紅WA綠的平臺了 屬實清新脫俗:)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章