/* http://blog.csdn.net/mobius_strip/article/details/39870555 这题涉及到了抽屉原理,也叫鸽巢原理,有时间不妨看看,我下载了相关文档 http://www.xuebuyuan.com/2224752.html 这个blog讲解得比较细致易懂,但是它的代码是RE的,不过思路和下面那串代码也是大同小异的,就没有改代码了 这题和一般的除法处理也很类似:不断被除数除以除数,商放入数组以备输出,余数(先保存,后面解释原因)*10作为新的被除数,再去得到除数...依次类推 为什么保存余数? 按照上面的描述,以及除法的规则,我们可以发现,只要在不断更新过程中,出现了之前出现过的余数,则循环节找到了,因为此后,就是这个相等的余数*10/被除数作商,取模被除数作余数,循环往复,关键还是找规律,发现结合除法的规则,这种情况,刚好就是找到了循环节的情况 可能用抽屉原理以后,理解这个会更快,不过目前也能想明白 此外,注意下左括号输出的条件,是在 i到min(50, cnt-1)之间,是否满足最后留下的a,所对应的位置flag[a]是等于i的,这点一定要想明白 又及,既然i从1开始,那么第一个余数,就应该是flag[a % b] = 1;(a和b没变化前),但那时对于q的处理,我们却是q[0] = a / b; 这就说明,在我的代码中,q数组并不和 r数组和flag数组,一一同步变化...这点一定一定要小心,当初就是一直错了这里,没有转过弯来 再次说明flag[i]== j意味着,在第j此做除法时,得到的余数时i,如果发现flag[i]不为0,说明前面的除法中,已经出现了余数为i的情况,也就意味着,找到了循环节 最后,这题的格式,又忘记格式控制了,耐心细致!WA使人崩溃,但如果时PE的话,真的十分可惜,尽量减少罚时 */ #include <iostream> #include <cstring> //#include <bits/stdc++.h> using namespace std; const int N = 5000; //注意数组不可开太小,否则RE int q[N], flag[N]; //三个数组分别对应商、余数,记录某个余数对应是在flag数组哪位出现,标记是否找到循环节,何处找到 int main() { int a, b, cnt; while (cin >> a >> b) { int tp = a; memset(flag, 0, sizeof(flag)); q[0] = a / b; a %= b; for (cnt = 1; a && !flag[a]; cnt++) // 退出这层循环,可能是因为余数为0了,也有可能是因为找到了循环节 { flag[a] = cnt; q[cnt] = a * 10 / b; a = a * 10 % b;// 很符合我们除法的规律,将余数*10再除以除数得商 } // for (int i = 0; i < cnt; i++) cout << q[i] << " "; cout << tp << "/" << b << " = " << q[0] << "."; //注意这几个 if-else 的出场顺序十分重要,有些虽然最后n为0,但不可以一开始就输出 (0,例如这组数据 76 25 for (int i = 1; i < cnt && i <= 50; i++) { if (a && flag[a] == i) //整除的情况后面有分支单独处理,此步考虑有循环节的情况,且此句对应着,现在就是碰到了循环节 cout << "("; cout << q[i]; } if (!a) cout << "(0"; if (cnt > 50) cout << "..."; cout << ")" << endl; // cout << "test: " << a << " " << flag[a] << endl; cout << " " << (!a?1:cnt - flag[a]) << " = number of digits in repeating cycle" << endl << endl; //flag[a]找对应余数为a的位置 } return 0; }