首页 > 代码库 > HDU 1717 小数化分数2
HDU 1717 小数化分数2
小数化分数2
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3040 Accepted Submission(s): 1239
Problem Description
Ray 在数学课上听老师说,任何小数都能表示成分数的形式,他开始了化了起来,很快他就完成了,但他又想到一个问题,如何把一个循环小数化成分数呢?
请你写一个程序不但可以将普通小数化成最简分数,也可以把循环小数化成最简分数。
Input
第一行是一个整数N,表示有多少组数据。
每组数据只有一个纯小数,也就是整数部分为0。小数的位数不超过9位,循环部分用()括起来。
Output
对每一个对应的小数化成最简分数后输出,占一行。
Sample Input
3
0.(4)
0.5
0.32(692307)
Sample Output
4/9
1/2
17/52
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1717
题目分析 :将该数分为两部分,即循环部分和非循环部分,最后答案为这两部分的和,设非循环部分的数字为num1,表示为分数结果是num1 / len1 (len1是num1的位数加1的基数)如0.32表示为32/100, 循环部分则要用到等比数列求和。设循环部分数字为num2,长度为len2 (len2是num2的位数加1的基数) 我们发现从小数点后的第k(k为基数的位数)位开始循环部分构成一个等比数列,其首项为 num2/len2,公比为1/len2,根据等比数列求和公式Sn = a1(1-q^n)/(1-q),这里q为1/len2显然len2>=10,因此当n趋向于无穷大的时候 (1/len2)^n趋向于0,所以Sn = a1/(1-q) = num2 / (len2 - 1)要注意Sn是从小数点后第k位算起的所以Sn还要除以len1
两个分数想加 a/b + c/d = (ad + bc) / bd,所以要求分数为(num1 / len1) + num2 / ((len2 - 1) * len1)化简后为
(num1 * (len2 - 1) + num2) / (len1 * (len2 - 1)),最后求分子分母的最大公约数通下分就是答案。这里说的还只是有循环小数的情况,没循环小数的情况就直接取num1 / len1,再通下分即可
//思路见代码,程序实现很简单 #include <cstdio> #include <cstring> int gcd(int a,int b) { return b == 0 ? a : gcd(b, a % b); } int main() { int T, len, flag; //nt1非循环部分分子 dt1非循环部分分母 //nt2循环部分分子,dt2循环部分分母 int nt1, nt2, dt1, dt2; char str[50]; scanf("%d",&T); while(T--) { flag = 1; nt1 = nt2 = 0; dt1 = dt2 = 1; scanf("%s", str); len = strlen(str); for(int i = 2; i < len; i++) { if(str[i] == '(') { flag = 0; continue; } if(str[i] >= '0' && str[i] <= '9') { if(flag) { dt1 *= 10; nt1 = nt1 * 10 + str[i] - '0'; } else { dt2 *= 10; nt2 = nt2 * 10 + str[i] - '0'; } } } if(flag) printf("%d/%d\n", nt1 / gcd(nt1, dt1), dt1 / gcd(nt1, dt1)); else { int temp = gcd(nt1 * (dt2 - 1) + nt2 , dt1 * (dt2 - 1)); printf("%d/%d\n", (nt1 * (dt2 - 1) + nt2) / temp, dt1 * (dt2 - 1) / temp); } } }