(超简单易懂)《算法竞赛入门经典》(第2版) 习题3-8循环小数 UVa202

前言

参考大佬博主的思路:https://blog.csdn.net/su_cicada/article/details/78939610

从这题我真的体会到了 “题题平等”,题目短它就简单了吗,题目长它就难了吗?虽然大部分情况下简单的题目是比较短,等下等下,再往下讲我觉得都上升到人生问题了,以上,END。:)
注:本文干货是 题目、思路、AC代码,其他都是废话,对,是的,没错,我就爱说废话,你怎么知道,太聪明了~

题目

UVa原题传送门:https://vjudge.net/problem/UVA-202

输入整数a和b(0<=a<=3000,1<=b<=3000),输出a/b的循环小数表示以及循环节长度。例如a=5,b=43,小数表示为0.(116279069767441860465),循环节长度为21。

思路

首先,你要知道这一点:
所有的分数,要么是有限小数,要么是无限循环小数!!!

接下来,手算一下除法1÷6,(对,就是用小学的除法算法),看看我的丑字,让我给看官娓娓道来,:
UVa202_method
我们用除法计算小数部分的过程,简单来说就是在进行不断的乘10取余,当然这里的分数要为真分数(比如7 / 6,我们就单独算整数部分1,剩下的1 / 6才是我们的操作对象,所以刚开始的时候,让分子7对分母6进行一次取余%运算即可)。

把每次乘10取余过程中的被除数、整除结果(即分数部分的值呀)存起来,当出现相同的被除数时,即循环开始了!小数循环体的起点就是当前遍历到的被除数的位置。如上图的1 / 6 起点为1 ,5 / 7 起点为 0 (在数组中下标要减1,vector容器也一样)。

为什么呢?嗯,这个问题嘛,因为想想就是啊,你想哈,当被除数相同,除数也相同,那不就是一样的计算过程了吗,就是不断在循环,一轮一轮的,不信你试试。
证明我可不会,比如你给我证明一下“ 1 + 1 = 2”呀,嘿嘿嘿。

ac代码心路历程

2020/3/11 早
太年轻,看完了UVa上的原题才意识到,我只是知道了一个常识:所有分数均可表示为无限循环小数。
然后其实我上面说的情况只是其中一种,还有1/250(小数部分有前导0),1/6(循环并不是从头开始的情况)。
昨晚我尝试了从局部推整体,想从特殊情况入手,也就是分类一下,直接暴力解题,嗯,以失败告终。
(小声bb:有些数据过了鸭hhhhhh,只能过特例…)
果然,这种从特殊情况入手,接着分类,进行暴力解题,很容易疏漏,且得出的答案并不适用于一般情况。
记录
2020/3/11 晚
看了几篇博客,阅读别人的代码真的好难,还是看不来,但是学到思路了,用被除数来做标识啊,另外在记录循环体开始的头部和长度!哇,帅,我要敲我的2.0,看我的,任意门!!!
hhh,AC了,好开心,经过两天的峰回路转,辗转反侧,终于柳暗花明,给我AC了!!!!!!!

AC代码

/*
	UVa202,ACM/ICPC World Finals 1990
	2.0
	reasonBao 
*/
#include <iostream>
#include <vector>

using namespace std;

int main() {
	int fenzi, fenmu;
	while (cin >> fenzi >> fenmu) {
		vector <int> dividement;	//记录每一步的被除数 
		vector <int> decimals;		//记录小数部分 
		int fenzi_beginner = fenzi;
		fenzi = fenzi % fenmu;	//化为真分数
		int cycle_begin = 0, cycle_end = 0;
		
		while (1) {
			fenzi = fenzi % fenmu * 10;
			bool is_over = false;
			
			for (int i = 0; i < dividement.size(); i++) {
				if (dividement[i] == fenzi) {
					cycle_begin = i;
					is_over = true;
				}
			} 
			if (is_over) break;
			decimals.push_back(fenzi / fenmu);
			dividement.push_back(fenzi);
		} 
//		cout << "dividement length = " << dividement.size() << endl;
//		for (int i = 0; i < dividement.size(); i++) 	cout << dividement[i] << " ";
//		
//		cout << "\ndecimals length = " << decimals.size() << endl;
//		for (int i = 0; i < decimals.size(); i++) 		cout << decimals[i] << " ";
//		
//		cout << "\ncycle_begin = " << cycle_begin << endl;
		
		int cycle_length = dividement.size() - cycle_begin;
		
//		cout << "cycle_length = " << cycle_length << endl;
		
		//开始打印结果咯
		int count_out = 0;
		cout << fenzi_beginner << "/" << fenmu << " = ";
		cout << fenzi_beginner / fenmu << ".";
		for (int i = 0; i < cycle_begin; i++) {
			cout << decimals[i];
			count_out++;
		}
		cout << "(";
		for (int i = cycle_begin; i < decimals.size(); i++) {
			cout << decimals[i];
			count_out++;
			if (count_out == 50) {
				cout << "...";
				break;
			}
		}
		cout << ")";
		cout << endl;
		cout << "   " << cycle_length << " = " << "number of digits in repeating cycle" << endl;
		cout << endl;
	} 
		
	return 0;
}

以下是代码1.0,Failed,蛮记录一下:

/*
	UVa202,ACM/ICPC World Finals 1990
*/
#include <iostream>
#include <vector>

using namespace std;

int main() {
	int fenzi, fenmu;
	while (cin >> fenzi >> fenmu) {
		//1. 整除的特殊情况直接处理
		if (fenzi % fenmu == 0) {
			printf("%d/%d = %d(0)\n", fenzi, fenmu, fenzi/fenmu); 
			printf("   %d = number of digits in repeating cycle\n", 1);
			continue;
		}
		
		int begin_fenzi = fenzi;
		vector <int> remainder_part;		 
		vector <int> decimal_part;
		fenzi %= fenmu;		//转化为真分数		
		int count_zero = 0; //计数,小数部分前面的0的个数 
		//2. 处理1/250 这类的小数前面0的情况,目标是化为100/250
		while (fenzi*10 < fenmu) {
			count_zero++;
			fenzi *= 10;
		} 
		fenzi *= 10;
		while(1) {
			bool is_over = false;
			decimal_part.push_back(fenzi / fenmu);
			for (int i = 0; i < remainder_part.size(); i++) {
				if (fenzi % fenmu == remainder_part[i]) {
					is_over = true;
				}
			}
			if (is_over) break;
//			decimal_part.push_back(fenzi / fenmu);
			remainder_part.push_back(fenzi % fenmu);
			fenzi = fenzi % fenmu * 10;
		}
		//开始输出结果 
		cout << begin_fenzi / fenmu << ".";
		for (int i = 0; i < count_zero; i++)	cout << "0";
		int pos = 0;
		for ( ; pos < decimal_part.size() - remainder_part.size(); pos++) {
			cout << decimal_part[pos]; 
		}
		cout << "(";
		for (int i = 0; i < remainder_part.size(); i++) {
			cout << decimal_part[i+pos];
		}
		cout << ")";
	}
	
	return 0;
}

进一寸有一寸的欢乐 —— > _ <

发布了32 篇原创文章 · 获赞 0 · 访问量 1168

猜你喜欢

转载自blog.csdn.net/qq_44296342/article/details/104767288