首页 > 代码库 > NYOJ131 小数相加 【字符串】

NYOJ131 小数相加 【字符串】

小数相加

时间限制:1000 ms  |  内存限制:65535 KB
难度:4
描述

给你两个个小数,你能计算出它们的和是多少吗?

你肯定会说,so easy。

可是,如果这些小数中有的是无限循环小数呢?

无限循环小数一般有三部分,整数部分,小数不循环部分,和小数循环部分。
比如:
1.2(34)的三部分分别为1 2 34.
2.(04)的整数部分为2,小数不循环部分不存在,小数循环部分为04
2.4的整数部分为2,小数不循环部分为4,小数循环部分不存在
一般小数循环部分在小数的最后。
现在,请计算两个无限循环小数的和


输入
第一行输入一个整数N,表示有N行测试数据(1<=N<=100)
第二行输入六个字符串S1,T1,R1,S2,T2,R2,分别别示第一个和第二个循环小数的整数部分,小数不循环部分与小数部分。(如果该部分不存在,则输入$)
整数部分,小数不循环部分,循环部分长度皆不超过10位。
输入的各部分皆为正数。
输出
输出两个数的和,输出结果请转换成最简分数(不要写成带分数的形式)。(如果是整数则直接输出)
样例输入
3
1 $ 3 2 $ 3
0 1 3 0 $ 6
2 03 $ 2 4 $
样例输出
11/3
4/5
443/100
来源
南阳理工学院第一次月赛队内组题目
上传者
张云聪

相当经典又恶心的一道题,昨天夜晚写到12点半都没调试出错误,好在刚才一起来就找到错哪里了+_+

关键是无限循环小数转换成最简分数的方法:对于x = a.bc其中a为整数部分,b为小数不循环部分,c为小数循环部分,转换成分数形式的方法为:x乘10的(strlen(b)+strlen(c))次方 - x乘10的strlen(b)次方 / (10的(strlen(b)+strlen(c))次方 -10的strlen(b)次方),其余形式的小数转换类似。


 
#include <stdio.h>
#include <string.h>

#define maxn 22
typedef long long LL;

char S[maxn], T[maxn], R[maxn];
int t;
LL a[2], b[2], c[3];

void getData(LL arr[]) {
	scanf("%s%s%s", S, T, R);
	if(S[0] == '$') S[0] = '0';
	sscanf(S, "%lld", &c[0]);
	if(R[0] == '$') {
		if(T[0] == '$') {
			arr[0] = c[0]; arr[1] = 1;
		} else {
			strcat(S, T);
			sscanf(S, "%lld", &arr[0]);
			LL tmp = 1;
			int len = strlen(T);
			for(int i = 0; i < len; ++i)
				tmp *= 10;
			arr[1] = tmp;
		}
	} else {
		if(T[0] == '$') {
			strcat(S, R);
			sscanf(S, "%lld", &arr[0]);
			int len = strlen(R);
			LL tmp = 1;
			for(int i = 0; i < len; ++i)
				tmp *= 10;
			arr[0] -= c[0];
			arr[1] = tmp - 1;
		} else {
			strcat(S, T);
			sscanf(S, "%lld", &c[1]);
			strcat(S, R);
			sscanf(S, "%lld", &c[2]);
			int len = strlen(T);
			LL tmp = 1;
			for(int i = 0; i < len; ++i)
				tmp *= 10;
			LL tmp2 = tmp; len = strlen(R);
			for(int i = 0; i < len; ++i)
				tmp2 *= 10;
			arr[0] = c[2] - c[1];
			arr[1] = tmp2 - tmp;
		}
	}
}

LL gcd(LL x, LL y) {
	return y ? gcd(y, x % y) : x;
}

void solve() {
	c[0] = a[0] * b[1] + a[1] * b[0];
	c[1] = a[1] * b[1];	
	if(c[0] % c[1] == 0) {
		printf("%lld\n", c[0] / c[1]);
		return;
	}
	LL tmp = gcd(c[0], c[1]);
	c[0] /= tmp; c[1] /= tmp;
	printf("%lld/%lld\n", c[0], c[1]);
}

int main() {	
	// freopen("stdin.txt", "r", stdin);
	scanf("%d", &t);
	while(t--) {
		getData(a);
		getData(b);
		solve();
	}
	return 0;
}


NYOJ131 小数相加 【字符串】