习题3-8 循环小数(Repeating Decimals, ACM/ICPC World Finals 1990, UVa202)

来源:互联网 发布:php 过滤二维数组重复 编辑:程序博客网 时间:2024/04/30 06:24
习题3-8 循环小数(Repeating Decimals, ACM/ICPC World Finals 1990, UVa202
输入整数ab0≤a≤30001≤b≤3000),输出a/b的循环小数表示以及循环节长度。 例

a=5b=43,小数表示为0.(116279069767441860465),循环节长度为21

点击打开链接链接在这里


前面的练习写过一题这样的小数输出题,

整数,

小数点,

题目意思有三种输出情况,

1      50以内能除尽,那就循环0;

2     50以内有循环单体,那就是当被除数与最开始进入循环相同的时候结束;

3     50以内除不尽,那就全部输出;

#include <bits/stdc++.h>using namespace std;int s,tp,a,len,num;int rep[51];int main(){    //freopen("input.txt","r",stdin);    while(~scanf("%d%d",&s,&a)){        printf("%d/%d = ",s,a);        printf("%d.",s/a);        s=(s-s/a*a);        len=0,num=0;        tp=s;        while(s!=0){            s*=10;            //cout<<"s="<<s<<endl;            ++len;            if(len<=50) rep[len]=s/a;            s=(s-s/a*a);            if(s==tp) break;        }        if(len>50){                printf("(");            for(int i=1;i<=50;i++){                printf("%d",rep[i]);            }                printf("...)");                num=len;        }        else if(s==0){            for(int i=1;i<=len;i++){                printf("%d",rep[i]);            }            printf("(0)");            num=1;        }        else{            printf("(");            for(int i=1;i<=len;i++){                printf("%d",rep[i]);            }            printf(")");            num=len;        }        printf("\n   %d = number of digits in repeating cycle\n\n",num);    }    return 0;}



上面那个代码提交到oj是错误的,原因有很多,主要是无法处理1/6,1/300这类的循环小数;因为判断循环的方法有问题;

正确的循环方法是任意一个第一次重复出现的s的pos1为循环节的起点,那重复的s之间的距离就是长度;

改进的AC代码如下


用了gcd对分数化简;

然后用cycle保存下标为s的情况是否出现过,first保存位置,second是bool;

#include <bits/stdc++.h>using namespace std;int len,s,a,num,pos1,pos2;typedef pair<int,bool> P;P cycle[30000];int rep[51];int gcd(int small,int big){    if(small>big) swap(small,big);    while(small!=0){        if(small>big) swap(small,big);        int tp=small;        small=big%small;        big=tp;    }    return big;}void simplify(){    int o=gcd(s,a);    s/=o;    a/=o;}int main(){    //freopen("input.txt","r",stdin);    while(~scanf("%d%d",&s,&a)){        memset(cycle,0,sizeof(cycle));        len=0;        num=0;        printf("%d/%d = %d.",s,a,s/a);        simplify();        s=10*(s%a);        while(1){                len++;            //cout<<endl<<"s="<<s<<"    "<<"len="<<len<<endl;            //cout<<"1--"<<cycle[s].first<<' '<<"2--"<<cycle[s].second<<endl;            if(cycle[s].second==true){                pos1=cycle[s].first;                pos2=len;                break;            }            else{                cycle[s].first=len;                cycle[s].second=true;            }            //cout<<"after"<<cycle[s].first<<' '<<cycle[s].second<<endl;            if(len<=50) rep[len]=s/a;            s=10*(s%a);        }        if(len>50){            for(int i=1;i<=50;i++){                if(i==pos1)printf("(");                printf("%d",rep[i]);            }            printf("...)\n");        }        else{            for(int i=1;i<=len-1;i++){                if(i==pos1)printf("(");                printf("%d",rep[i]);            }            printf(")\n");        }        num=pos2-pos1;        printf("   %d = number of digits in repeating cycle\n\n",num);    }    return 0;}



阅读全文
0 0
原创粉丝点击