poj 1930 Dead Fraction 混循环小数化分数 数论

Dead Fraction
Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 2417 Accepted: 782

Description

Mike is frantically scrambling to finish his thesis at the last minute. He needs to assemble all his research notes into vaguely coherent form in the next 3 days. Unfortunately, he notices that he had been extremely sloppy in his calculations. Whenever he needed to perform arithmetic, he just plugged it into a calculator and scribbled down as much of the answer as he felt was relevant. Whenever a repeating fraction was displayed, Mike simply reccorded the first few digits followed by "...". For instance, instead of "1/3" he might have written down "0.3333...". Unfortunately, his results require exact fractions! He doesn't have time to redo every calculation, so he needs you to write a program (and FAST!) to automatically deduce the original fractions. 
To make this tenable, he assumes that the original fraction is always the simplest one that produces the given sequence of digits; by simplest, he means the the one with smallest denominator. Also, he assumes that he did not neglect to write down important digits; no digit from the repeating portion of the decimal expansion was left unrecorded (even if this repeating portion was all zeroes).

Input

There are several test cases. For each test case there is one line of input of the form "0.dddd..." where dddd is a string of 1 to 9 digits, not all zero. A line containing 0 follows the last case.

Output

For each case, output the original fraction.

Sample Input

0.2...
0.20...
0.474612399...
0

Sample Output

2/9
1/5
1186531/2500000

Hint

Note that an exact decimal fraction has two repeating expansions (e.g. 1/5 = 0.2000... = 0.19999...).

Source


#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>

/*
  我觉得如果你没有思路的话,你应该先去看看数论里面的小数化成分数是怎么化的,
  然后把数学语言转化为计算机的代码
  混循环小数=有限小数+纯循环小数
  纯循环小数:9的个数就是循环节的个数,0的个数就是非循环节的个数(就是有限小数那部分) 
  
  我的代码思路: 0.474612399...= up2/down2 + up1/down1; 
  up1,down1对应有限小数那部分     up2,down2对应纯循环小数那部分 
  
  当然我的代码中有可以化简得部分,如果有pow()函数的话,注意形式(int)( pow() ),注意强制转化
  因为pow()函数的结果是浮点型 
*/ 
using namespace std;
char str[1100];
long long  len;
long long numbersof0,numbersof9;//分别保存0的个数和9的个数 

long long gcd(long long a,long long b)//求分子分母的最大公约数 
{
	if(b==0)
	return a;
	else
	return gcd(b,a%b);
}

long long  cal_up1()//计算up1 
{
	long long  up1=str[2]-'0';
	int k=3;
	int i;
	for(i=2;i<=numbersof0;i++)
	{
		up1=up1*10+(str[k]-'0');
		k++;
	}
	return up1;
}

long long cal_up2(int i)//计算up2 
{
	long long  up2=str[i]-'0';
	int j;
	for(j=i+1;j<=len-4;j++)
	{
		up2=up2*10+(str[j]-'0');
	}
	return up2;
}

long long  cal_down1()//计算down1 
{
	long long down1=1;
	int i;
	for(i=1;i<=numbersof0;i++)
	{
		down1=down1*10;
	}
	return down1;
}

long long  cal_down2()//计算down2 
{
	long long down2=0;
	int i;
	for(i=1;i<=numbersof9;i++)
	{
		down2=down2*10+9;
	}
	for(i=1;i<=numbersof0;i++)
	{
		down2=down2*10;
	}
	return down2;
}

int main()//题目要用long long 或者 __int64,要不然会数据溢出的 
{

	long long up1,up2,down1,down2;//为了与上面区别,所以未定义全局变量 
	long long gc;//最大公约数存储 
	long long minup,mindown;//最终的结果存储位置 
	while( scanf("%s",str)!=EOF )
	{
		if(strcmp(str,"0")==0)
		break;
		
		len=strlen(str);
		int i;
		for(i=2;i<=len-4;i++)//循环节开始的位置坐标 
		{
			numbersof0=i-2;
			numbersof9=len-4-i+1;
			if(i==2)//i==2的时候记得特判 
			{
				up2=cal_up2(i);//这里计算up2的时候注意别忘了参数的传递 
				down2=cal_down2();
				gc=gcd(up2,down2);
				minup=up2/gc;
				mindown=down2/gc;
			}
			else
			{
				up1=cal_up1();
				down1=cal_down1();
				up2=cal_up2(i);
				down2=cal_down2();
				long long newup=up2*down1+up1*down2;
				long long newdown=down1*down2;
				gc=gcd(newup,newdown);
				newup=newup/gc;
				newdown=newdown/gc;
				if(newdown<mindown)
				{
					minup=newup;
					mindown=newdown;
				}
			}
		}
		printf("%lld/%lld\n",minup,mindown);
		memset(str,0,sizeof(str));
	}
	return 0;
}
下面附上一组测试数据,你要是wrong  的话,可以试试
上个链接吧http://poj.org/showmessage?message_id=29540

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值