这是一道模拟题。模拟题的第一要义就是把我们手动做这件事的逻辑理顺并以代码的形式表述出来。所以我第一步思考的是:「我是如何计算小数的?」「我是如何确定循环节的?」显然,我会观察每一次除的时候,这个被除数(即上一步的余数乘以 10)是否已经出现过。如果已经出现过,说明有循环节。
这说明需要一个记簿。我们使用 unordered_map<Dividend, BitPos>
,以被除数为键(因为我们查询的对象就是它),它出现的位数为值。因为这些记录不需要有序,所以使用哈希表而不是红黑树。
#include <cstdint>
#include <iostream>
#include <unordered_map>
int main() {
using u32 = uint32_t;
u32 t;
std::cin >> t;
for (u32 i = 0; i != t; ++i) {
u32 n, m;
std::cin >> n >> m;
std::cout << "case #" << i << ":\n" << n / m;
n = n % m * 10;
if (!n) {
std::cout << '\n';
continue;
}
std::cout << '.';
using BitPos = u32;
using Dividend = u32;
u32 bit_cnt = 1;
std::unordered_map<Dividend, BitPos> table{{n, bit_cnt}};
do {
std::cout << n / m;
n = n % m * 10;
if (auto [it, ok] = table.insert({n, bit_cnt += 1}); !ok) {
std::cout << '\n' << it->second << '-' << bit_cnt - 1;
break;
}
} while (n);
std::cout << '\n';
}
}
包代码时三个点的中英文模式没切换对(大雾