HDU-#1717 小数化分数2(巧妙的推导式)

本文详细解析了一道经典题目,即如何将循环小数转换为最简分数。通过将小数分为三部分:头、不循环小数部分和循环小数部分,然后运用数学技巧和算法实现转换。特别介绍了如何使用`sscanf`函数从字符串中截取所需数据,并对求解过程进行了详细的步骤说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        题目大意:给出小数(包括纯小数以及循环小数),求对应的最简分数。

        解题思路:很经典的一道题目,自己模拟了半天也没弄出来,后边看了大神的解题报告才知道如此的巧妙。自己推了一下,然后拍了!自己曾经热爱的数学,那么久没碰过,居然生疏得完全没有灵感了!唉...针对这个题给出几点说明:一是这个题可以很灵活的处理,自己还在那里傻推..这里可以直接将小数分为三部分,第一部分就是头:"0.",第二部分就是不循环的小数部分,记着S1,长度为n,第三部分为循环小数部分记着S2,长度为m。由此我们先将小数乘以10^n,那么就将小数化为X*10^n=S1+Y(0.y1y2...ym)。再将Y部分同理可得:Y*10^m=S2+Y.合并可得:X=(S1*((10^m)-1)+S2)/((10^n)*((10^m)-1))。然后对这个式子分为三种情况求解:两部分长度n和m其中一个为0的情况以及两个都不为0的情况进行求解即可得。最后是一个小细节的应用,接收数据是字符串型的,而后边我们需要对该字符串的部分数据进行截取,可以用头文件为<stdio.h>中的sscanf来进行接收,直接就可以获取你想要的部分,具体应用参见这里解释。其它详见code。

        题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1717

       code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

const int MAXN = 15;
int n,m,t;
char num[MAXN];

int gcd(int a,int b){
    return b==0 ? a : gcd(b,a%b);
}

int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%s",num);
        int len = strlen(num);
        int i,s1,s2;
        for(i=0;i<len;i++)
            if(num[i]=='(') break;
        n=i-2;
        m=len-4-n;
        if(n==len-2){
//            for(int j=2;j<n+2;j++){
//                s1+=num[j]-'0';
//                if(j!=n+1) s1*=10;
//            }
            sscanf(num+2,"%d",&s1);
            int f=(int)pow(10,n);
            int g=gcd(s1,f);
            printf("%d/%d\n",s1/g,f/g);
        }
        if(m==len-4){
//            for(int j=3;j<m+2;j++){
//                s2+=num[j]-'0';
//                if(j!=m+1) s2*=10;
//            }
            sscanf(num+3,"%d",&s2);
            int f=(int)pow(10,m)-1;
            int g=gcd(s2,f);
            printf("%d/%d\n",s2/g,f/g);
        }
        if(m>0 && n>0){
//            for(int j=2;j<n+2;j++){
//                s1+=num[j]-'0';
//                if(j!=n+1) s1*=10;
//            }
//            for(int j=len-m-1;j<len-1;j++){
//                s2+=num[j]-'0';
//                if(j!=len-1) s2*=10;
//            }
            sscanf(num+2,"%d",&s1);
            sscanf(num+n+3,"%d",&s2);
            int c=s1*((int)pow(10,m)-1)+s2;
            int d=(int)pow(10,n)*((int)pow(10,m)-1);
            int g=gcd(c,d);
            printf("%d/%d\n",c/g,d/g);
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值