题解
做该题要有耐心,把题目分析透彻。将该问题分为三种情况:
第一情况:能够整除。判断方法:a除以b的余数为0,即a%b==0;
不能整除情况:整数部分为a/b,其余数为a%b。按照除法法则,将余数放大10倍继续除以b可以依次得到小数点之后的商值。采用循环的形式,不断将a除以b的余数重新赋值给a,即a=a%b,在通过a=a*10和a/b得到下一位的商。这里我们分两种情况考虑:
第二种情况.在该循环中,最终a被b整除。这是,依次输出循环中得到的商值即可,为有限小数情况。
第三章情况.当为循环小数情况时,a永远不会被b整除。这里考虑循环小数特点:当a除以b其余数与之前得到的余数相同时,说明得到的商值从该处开始循环。
因此,循环的终止条件有两个,余数为0或者余数重复出现。由于存在两种情况,我们对于循环中得到的商值不能直接输出,需要用数据结构进行存储,这里最合适用按需分配容量的vector进行存储。
当余数为0时,直接输出vector里的值;
当余数不为0时,找点商开始循环的位置,其之前直接输出,之后到末尾放入“()”中输出。难点:商值开始循环即在循环体中余数a重复出现,使用Map m,用其count()函数返回被查找元素的个数,来判断余数是不是重复出现,如果没有,返回0;否则,返回1退出循环。由于,每得到一个余数的同时就会得到一个商,用一个变量t记录在退出循环前产生的余数a是第几个产生的,并将该余数a放入m中时用该t值作为其value值。退出循环后,通过m[a]的即可以判断何时输出“(”。
#include<iostream> #include<map> #include<vector> using namespace std; int main() { int a, b, t; map<int, int> m; vector<int> vec; cin >> a >> b; cout << a / b; a = a % b; //对于整除情况直接结束 ,否者输出小数点 if(a == 0) return 0; cout << "."; //记录余数何时出现 t = 0; //将商存入vector,余数存于map,直到余数为0或者重复出现时退出循环 while(a != 0) { if(m.count(a) != 0) break; vec.push_back(a * 10 / b); m[a] = t++; a = a * 10 % b; } /*余数为0时,为有限小数,直接输出vector的值; 当余数重复出现,通过count()函数找到循环位置开始处,vector输出时在该位置加入“(”,末尾加入“)”*/ if(a == 0) { for(int i = 0; i < t; i++) cout << vec[i]; } else { int k = m[a]; for(int i = 0; i < k; i++) cout << vec[i]; cout << "("; for(int i = k; i < t; i++) cout << vec[i]; cout << ")"; } cout << endl; return 0; }