Repeating Decimals UVA - 202

这道题其实要明白一个特点(见绿书22页)但某一次a%b如果与之前出现的a%b值一样(我们设该值为X,即设a%b==X),那么X除以b的值也是和第一次的a%b除以b的值一样,其余数也一样,于是乎,之后的值和余数也是这样,如此,就产生了循环(见下图)

 

#include <bits/stdc++.h>
using namespace std;
bool r[3005];//该余数是否出现过 
int t[3005];//t[i]表示第一次出现余数为i时属于输出的字符串(就是a/b的值,我们把它作为字符串输出)的第几位,例如若为0.33333,则t[1]会被标记(因为1%9 == 1),则出现余数为1时是字符串的第三位,(第一次出现余数为1时是在0.3的3这个字符上,0为第一个字符,'.'为第二,'3'为第三 
char temp[3005];//保存带小数点的字符串 
int ori_num;//代表小数从输出的字符串的第ori_num位开始 
int main()
{
	int a, b;
	while(scanf("%d %d",  &a, &b) != EOF)
	{
		string ans;
		memset(r, 0, sizeof(r));
		sprintf(temp, "%d.", a / b);//将小数点和其前面的结果保存在temp中 
		printf("%d/%d = ", a, b);
		ans += temp;
		int t_num = ans.size();
		ori_num = t_num;//保存小数点的位置,因为如果循环节超过了50就要保留前50位小数,这个用作标记 
		a %= b;
		do{
			r[a] = true;//余数为a出现第一次 
			t[a] = t_num++;//第一次出现余数a是在位置t_num上 
			a *= 10;//正常除法不够就补0 
			ans += (a / b) + '0';
			a %= b;
		}while(!r[a]);//如果r[a]为真则余数为a的情况出现过了 
		int size = t_num - t[a];//计算循环节长度 
		if(ans.size() - ori_num > 50)//如果此时已经超过50位小数,补上省略号 
		{
			ans.erase(ori_num + 50, ans.size() + 1 - ori_num - 50);//删掉50位后面的 
			ans += "...";
		}
		ans.insert(t[a], 1, '(');//从第一次出现余数为a的地方之前补上"(" 
		ans += ')';
		cout << ans << endl;
		printf("   %d = number of digits in repeating cycle\n\n", size);
	}
	return 0;
}

  

 

posted @ 2020-05-13 21:25  funforever  阅读(123)  评论(0编辑  收藏  举报