输入整数a和b(0<=a<=3000,1<=b<=3000),输出a/b的循环小数表示以及循环节长度。例如a=5,b=43,小数表示为
0.(116279069767441860465),循环节长度为21;
思路:分数不能表示无限不循环小数。建立3个数组,一个放商,一个放余数,一个对应下角标的数若是余数则元素为1,即记录余数存在。循环除数加一次,若余数为0,则循环节长度为1,若当前得到的余数已经存在,则有循环节,求出2个相同余数的距离即为循环节长度。
这个主要是怎么寻找循环节,在除法计算的过程中如何判断一个循环节已经出现了。循环节第二次出现意味着计算过程中的余数已经第二次出现。其实自己在草纸上写一个比如5/7就能发现。当商5的时候(5是循环节的最后一位)余数是5,这和第一次商0的时候(0是循环节前一位)余数也是五。然后用索引存储是否这个余数已经出现过,还有一个数组记录余数对应的商的位置。余数的范围是1~m-1,所以循环节最长是m-1,所以查询数组的大小根据m的值来设定
- #include <iostream>
- #include <cstdlib>
- #include <cstring>
- #include <cstdio>
- using namespace std;
- int r[3003],u[3003],s[3003];
- int main()
- {
- int n,m,t;
- while (cin >> n >> m) {
- t = n;
- memset(r, 0, sizeof(r));
- memset(u, 0, sizeof(u));
- int count = 0;
- r[count ++] = n/m;
- n = n%m;
- while (!u[n] && n) {
- u[n] = count;
- s[count] = n;
- r[count ++] = 10*n/m;
- n = 10*n%m;
- }
- printf("%d/%d = %d",t,m,r[0]);
- printf(".");
- for (int i = 1 ; i < count && i <= 50 ; ++ i) {
- if (n && s[i] == n) printf("(");
- printf("%d",r[i]);
- }
- if (!n) printf("(0");
- if (count > 50) printf("...");
- printf(")\n");
- printf(" %d = number of digits in repeating cycle\n\n",!n?1:count-u[n]);
- }
- return 0;
- }