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