题解

做该题要有耐心,把题目分析透彻。将该问题分为三种情况:

第一情况:能够整除。判断方法: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;
}