数与连分数

来源:Vijos 1696
数与连分数
描述
写一个程序…可以实现在连分数和分数之间的互相转换…

样例1
样例输入1
[2;3,7]
51/22

样例输出1
51/22
[2;3,7]

提示
多组测试数据:
…每一个测试点有多组数据…数据的组数不超过100组…
约分:
计算结果最后是要约分的…但是…在分数转向连分数的时候…
我们不保证输入的数据是约分…
Range:
数字的规模都很小…
也就是它们都不会超过longint范围里…
包括中间的数据…
连分数的项数也不会超过100项…

限制:
出题人不透露

考点:模拟枚举?)
这个题只需要了解连分数的知识就应该可以比较容易解决,我认为这个题就仅仅是模拟两个算法:数-连分数,连分数-数;不知道这个题为什么被打上了枚举的标签(如果你认为顺序或逆序遍历也算枚举的话当我没说)。
首先上连分数的知识,这里不想给具体定义,就给个实例,应该很容易理解:
在这里插入图片描述
右边对应的表示形式是[3;4,12,4],理解后很容易构思算法。上代码:

#include <iostream>
#include <cstring>
#define MAXN 307
#define IsDigit(x) (x >= '0' && x <= '9')
using namespace std;
char str[MAXN];
int len, sum, cun[MAXN], res[MAXN];

int gcd(int a, int b)
{
	return (b == 0) ? a : gcd(b, a % b); 
}

//连分数-数
void Work1()
{
	int sup, a, b, pos = 0, t = 1;
	//提取数字并存储在数组里
	while (t < len)
	{
		sum = 0;
		while (IsDigit(str[t]) and t < len)
			sum = sum * 10 + str[t++] - '0';
		cun[pos++] = sum;
		++t;
	}
	a = 1, b = cun[pos - 1];
	for (int i = pos - 2; i >= 0; --i)
		a += cun[i] * b, swap(a, b);
	//特例
	if (a == 1) cout << b << endl;
	else cout << b << "/" << a << endl;
}

//数-连分数
void Work2()
{
	int a, b, t = 0, tmp, GCD;
	//同上
	while (t < len)
	{
		sum = 0;
		while (IsDigit(str[t]) and t < len)
			sum = sum * 10 + str[t++] - '0';
		if (str[t] == '/') a = sum;
		++t;
	}
	b = sum, t = 0;
	//约分
	GCD = gcd(a, b), a /= GCD, b /= GCD;
	//特例
	if (b == 1) cout << "[" << a / b << "]\n";
	else
	{
		while (b != 1)
		{
			tmp = a / b;
			res[t++] = tmp, a -= tmp * b;
			swap(a, b);
		}
		res[t++] = a;
		cout << "[" << res[0] << ";";
		for (int i = 1; i < t - 1; ++i)
			cout << res[i] << ",";
		cout << res[t - 1] << "]" << endl;
	}
}

int main()
{
	while (cin >> str)
	{
		len = strlen(str);
		if (str[len - 1] == ']') Work1();
		else Work2();
	}
	return 0;
}

需要注意的几点:
1.这个题输入输出比较麻烦,需要将字符串中的数字提取出来,还要把计算后的结果用题目要求的形式输出;
2.约分的问题:用辗转相除法求最大公约数,上下同除即可得到最简分数;
3.某些特例:[4] = 4,不是4/1; 4/1 = [4],不是[4;]。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值