FZU Problem 2223 神奇的计算器

 Problem 2223 神奇的计算器

Accept: 11    Submit: 79
Time Limit: 1000 mSec    Memory Limit : 32768 KB

 Problem Description

为了帮助正在学习除法的表弟,Yellowstar想制作一个计算器,它能给出整数除法的完整结果。

具体来说,给出两个整数m、n:

如果m/n是整数或有限小数,那么直接输出它的值。

如果m/n是无限小数,那么输出小数点后到第一个最小循环节为止,并用”()”把最小循环节括起来。

 Input

输入第一行为一个正整数T,表示有T组测试数据。

接下去T行,每行为一组数据。每行两个正整数m、n,含义如上。

T<=15,1<=m,n<=2^31-1。

 Output

每个样例一行,输出答案。

注意计算器的屏幕最多能输出1 000 000个字符(包括小数点和括号,不包括结尾的换行),如果某组数据的结果超过了这个长度,那么该组数据输出”Too long”而不是原答案。

 Sample Input

44 21 5123 7652 1380779

 Sample Output

20.20.1(6078431372549019)Too long

 Source

FOJ有奖月赛-2016年4月(校赛热身赛)

 

思路:该题目有4种情况1、m%n == 0;对于这种情况最简单了,直接输出m/n;然后其他情况就需要模拟一下除法来保存m/n的整数部分和小数部分,n是固定不变的,而你识不断变化的,根据鸽巢原理就可以知道肯定存在m变化的过程中会出现一个m'/n == m/n,这就意味着循环节出现了,但我们每次需要标记m,而m的范围是1<=m<=2^31-1,我们开不了这么大的数组,只能用Hash表把新得到的m'存好,没得到了一个m'就通过索引去寻找当前的m'是是否被标记了,后面就很简单了。

代码:

#include <cstdio>
#include <cstring>
typedef long long ll;
const int maxn =  1000000+1024;
const int maxm =  1000007;
int Head[maxn],Next[maxn],top;
ll key[maxn],x,y,a,b,t,bit[maxn];
ll n,cnt;
bool getVis(ll s)
{
	int pos = (int)s%maxm;
	for(int i = Head[pos];i;i = Next[i])
	{
		if(key[i] == s) return true;//当前的Hash中存在这个数了,返回true
	}
	return false;//没有就返回false
}
void Intert(ll s)
{
	int pos = (int)s%maxm;//获取索引
	Next[top++] = Head[pos];
	Head[pos] = top;
	key[top] = s;
}
int main()
{
#ifdef CDZSC_June
	freopen("t.txt","r",stdin);
#endif // CDZSC_June
	scanf("%I64d",&n);
	while(n--)
	{

		top = 0; memset(Head,0,sizeof(Head));
		cnt = 0;
		scanf("%I64d%I64d", &a, &b);
		x = a,y = b;
		if(x%y == 0){//能够整除,直接输出
			printf("%I64d\n",x/y);
		}
		else
		{
			bit[cnt++] = x/y;
			a %= b;
			bit[cnt++] = a*10/b;
			Intert(0); Intert(a);
			a = a*10%b;
			while(!getVis(a))
			{
				bit[cnt++] = a*10/b;
				Intert(a), a = a*10%b;
				if(cnt > 1000000)break;
			}
			if(a == 0)//有限小数,直接输出数组里面的元素
			{
				printf("%I64d.",bit[0]);
				for(int i = 1; i<cnt; i++)
				{
					printf("%I64d",bit[i]);
				}
				puts("");
			}
			else
			{
				t = a;
				if(cnt > 1000000){//循环节过长了,输出Too long
					puts("Too long");
				}
				else{//有限循环小数,输出该数和它的循环节
					printf("%I64d.",bit[0]);
					for(int i =1;i<cnt;i++)
					{
						if(bit[i] == a*10/b) break;
						printf("%I64d",bit[i]);
					}
					printf("(");
					do 
					{
						printf("%I64d",a*10/b);
						a = a*10%b;
					} while (a != t);
					printf(")\n");
				}
			}
		}
	}
	return 0;
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值