UVA202 题解

发布时间 2023-09-09 18:49:35作者: 群星之路

思路分析

前言

又是一道小模拟题,不过细节巨多,可以用来锻炼自己的代码能力。

解法

本题实际上就是模拟长除法的计算过程,其中每一步除法时都有被除数及其余数,当被除数出现重复时就表示出现循环节了。所以需要记录每一次的被除数及其在循环小数中的位置,需要判断当除数不够除,每一次补零也需要记录其对应的位置。

代码实现

#include <cstdio>
#include <string>
#include <unordered_map>

const int MAXN = 3e3 + 10;

std::unordered_map<int, int> map;

void solve(int n, int d, std::string &ans, int &r) {
	ans = ".";
	map.clear();
	while (true) {
		n *= 10;
		auto p = map[n];
		if (!p) map[n] = ans.size();
		else {
			r = ans.size() - p; // 找到了循环节
			if (r > 50) ans.erase(p + 50), ans += "...";
			ans.insert(p, "(");
			ans += ')';
			break;
		}
		if (n < d) { // 补零
			ans += '0';
			continue;
		}
		int div = n / d, mod = n % d;
		ans += div + '0';
		n = mod;
		if (!n) {
			ans += "(0)", r = 1;
			break;
		}
	}
}

int main() {
	int a, b, r;
	std::string ans;
	while (scanf("%d%d", &a, &b) == 2) {
		ans = ".(0)", r = 1; // r 用于记录循环节长度
		if (a % b) solve(a % b, b, ans, r);
		printf("%d/%d = %d%s\n", a, b, a / b, ans.c_str());
		printf("   %d = number of digits in repeating cycle\n\n", r);
	}
	return 0;
}