Page 59
Description
输入整数a和b(0<=a<=3000,1<=b<=3000),输出a/b的循环小数表示以及循环节长度。
Sample Input
76 25
5 43
1 397
Sample Output
76/25 = 3.04(0)
1 = number of digits in repeating cycle
5/43 = 0.(116279069767441860465)
21 = number of digits in repeating cycle
1/397 = 0.(00251889168765743073047858942065491183879093198992...)
99 = number of digits in repeating cycle
分析:数论,组合。
n除以m的余数只能是0~m-1,根据抽屉原则,当计算m+1次时至少存在一个余数相同,
即为循环节;存储余数和除数,输出即可。
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cctype>
#include<cmath>
using namespace std;
#define M 3005
int r[M],u[M],s[M];
int main()
{
//freopen("in.txt","r",stdin);
int n,m,t,i;
while (cin >> n >> m) {
t = n;
memset(r, 0, sizeof(r));
memset(u, 0, sizeof(u));
int cnt = 0;
r[cnt ++] = n/m;
n = n%m;
while (!u[n] && n) { //余数!=0且余数没有出现过
u[n] = cnt;
s[cnt] = n; //存第cnt个余数
r[cnt ++] = 10*n/m; //存第cnt个小数
n = 10*n%m;
}
printf("%d/%d = %d.",t,m,r[0]);
for (i = 1 ; i < cnt && i <= 50 ; ++ i) { //结束取50和循环长度的较小者
//先有余数,后有对应小数,弄清这点对判断循环节开始的位置很重要
if (n && s[i] == n) printf("(");
printf("%d",r[i]);
}
if (!n) printf("(0");
if (cnt > 50) printf("...");
printf(")\n");
printf(" %d = number of digits in repeating cycle\n\n",!n?1:cnt-u[n]);
}
return 0;
}