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;
}

浙公网安备 33010602011771号