Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 1198 | Accepted: 354 |
Description
Input
Output
Sample Input
0.2... 0.20... 0.474612399... 0
Sample Output
2/9 1/5 1186531/2500000
Hint
Source
/* 这题主要是给出一个无限循环小数,要求去求他所对应的具有最小分母的分数。无限循环小数转换为分数有 一定的规律和方法可循: (1)假设输入小数为0.i1 i2 ... it j1 j2 ... jk,即j1 j2 ... jk是循环的部分 那么这个分数可以分两部分来计算即不循环的部分和循环的部分. (2)先来看不循环的部分,这个非常简单.即为 i1i2 ... it / 10 ^ t,即不循环部分的分子分母分别为: upd = i1 i2 ... it; downd = 10 ^ t; (3)再来看循环部分,这部分有点难.在数论中的典型做法是: 取分子up为:j1 j2 ... jk 分母down为: 10 ^ (t + k) - 10 ^ t (4)那么最后所得的分数即为: upd / downd + up / down = (upd * down + downd * up) / (down * up) (5)注意计算的时候要约分.另外由于题目没有明确给出循环部分的长度,所以需要自己枚举,然后计算出 所有的分数取分母最小的.另外要注意的是输入中含有全0的情况(输出0/1),这个太恶心了,因为题目明确说 了输入不全为0的,害我WA了好几次. */ #include <iostream> #include <cmath> #include <cstring> using namespace std; char input[20]; int spos, epos; __int64 minup, mindown; __int64 gcd(__int64 a, __int64 b) { if(b == 0) return a; else return gcd(b, a % b); } //利用最大公约数来约分 void trim(__int64 &up, __int64 &down) { __int64 gcdval; while((gcdval = gcd(up, down)) != 1) { up /= gcdval; down /= gcdval; } } //判断是否全0 bool allZero() { for(int i = strlen(input) - 4; i >= 2; i--) if(input[i] != '0') return false; return true; } int main() { while(scanf("%s", input) && strcmp(input, "0") != 0) { //当不全0时 if(!allZero()) { mindown = -1; epos = strlen(input) - 4; //输入字符串数字位的结束位置 spos = 2; //小数点后面的起始位置 __int64 up = 0, down = 0, upd = 0, downd = 0, dupdown; //枚举循环部分的起始位置 for(int t = spos; t <= epos; t++) { upd = up = 0; int k = spos; while(k < t && input[k] == '0') k++; //找到非循环部分第一个不为0的位置 for(; k <= epos; k++) { if(k < t) upd = upd * 10 + int(input[k] - '0'); //统计非循环部分的分子值 if(k >= t) up = up * 10 + int(input[k] - '0'); //统计循环部分的分子值 } downd = pow(10.0, t - spos); //非循环部分的分母值 down = pow(10.0, epos - spos + 1); //所有小数部分的分母值 dupdown = pow(10.0, epos - t + 1); //循环部分的分母值 down = down - down / dupdown; //制造循环部分小数的最终分母值 if(up != 0) trim(up, down); //约分 if(upd != 0) trim(upd, downd); //约分 __int64 newup, newdown; newup = up * downd + down * upd; newdown = down * downd; if(newup != 0) trim(newup, newdown); //计算最终结果 if(mindown == -1 || newdown < mindown) //取分母最小的 { mindown = newdown; minup = newup; } } printf("%I64d/%I64d/n", minup, mindown); } //全为0的情况 else printf("0/1/n"); } return 0; }