hdu 1717 小数化分数2 (循环小数转分数)

来源:互联网 发布:如何申请淘宝直播达人 编辑:程序博客网 时间:2024/05/01 06:39

题目链接:点击打开链接


本题可推出公式

首先跟你一个小数 令X= 0 . s1 s2 ..sn ( y1 y2 y3..ym ) 这样的话我们把小数点分为三个部分,分别用三种颜色标记了!

我们可以把表达式转换成:X * 10 ^n=s1s2..sn+0.y1y2..ym;    我们用S1替换 s1s2..sn ,Y替换 0.(y1y2..yn), 然后可以把表达式写成: X * 10^n=S1 + Y;  然后 Y=0.(y1y2..ym) 变形一下:Y * 10 ^m=y1y2..ym + Y; 在这里我们另y1y2..ym等于S2;

宗上所述:我们得到两个表达式 X * 10^n=S1 +  Y;    Y * 10^m=S2 + Y; 然后将两个式子合并成一个用表达式,

$$\frac{s2 + (10^m-1)*s1}{10^n * ( 10^m -1 )}$$然后就可以根据这个公式,求出分子分母的 最大公约式 然后化简 就可以了


由此只需算出s1,s2,m,n即可,从字符串中读数使用sscanf,格式化读入可用 sscanf(c,"0.%d(%d)",&s1,&s2); 。

算m,n时不能按s1,s2位数算,因为前面可能有0,如0.0(1)这个数、

算平方真心不能用pow,精度太低了,,,wa了几次


代码:

#include <cstdio>#include <cstring>#include <iostream>#include <cmath>using namespace std;int gcd(long long a,long long b){    if(b==0)return a;    else return gcd(b,a%b);}char c[20];int main(){    int T;    cin>>T;    while(T--){        scanf("%s",c);        int s1,s2;        int flag=1;        for(int i=1;i<strlen(c);i++){            if(c[i]=='('){flag=0;break;}        }        if(flag){ sscanf(c,"0.%d",&s1); s2=0;}        else if(c[2]=='(') {sscanf(c,"0.(%d)",&s2); s1=0;}        else sscanf(c,"0.%d(%d)",&s1,&s2);        char t[20];        int m=0,n=0;        if(flag) {m=strlen(c)-2;n=0;}        else {            int i;            for(i=2;i<strlen(c);i++){                if(c[i]!='(') m++;                else break;            }            i++;            for(;i<strlen(c);i++){                if(c[i]!=')') n++;                else break;            }        }        int k1=1;        int k2=1;        for(int i=1;i<=m;i++){            k1*=10;        }        for(int i=1;i<=n;i++){            k2*=10;        }        long long a=s2+s1*(k2-1);        long long b=(k2-1)*k1;        if(flag) {a=s1;b=k1;}        int k=gcd(a,b);        a/=k;        b/=k;        printf("%I64d/%I64d\n",a,b);    }    return 0;}


0 0