习题3-8 循环小数 UVa202

算法竞赛入门经典(第2版)第3章 数组和字符串
习题3-8 循环小数 UVa202
感悟。
1、意识到除了getchar可以有EOF,scanf也可以有。

2、熟悉了小学除法的运算原理,很快将结果用整型数组表示,只要数组长度允许可以算到任意长度的小数。

3、但在一堆数据里找循环节上卡住了。

4、很想参考他人成果,忍住了,来来回回写了好几种,但都觉得太烦,放弃了,要写尽量简单易懂的代码。

5、在写了擦除,擦除了写的过程中,解决了循环节问题,看看代码还是挺简洁的。

6、本以为该收获成果了,没想到输出格式也挺繁琐,硬着头皮,写,就是费点工而已。

7、提交,Runtime error,学会了在cmd(命令行下)abc < a.in枚举排错,将0<=a<=3000,1<=b<=3000全部测试了一遍,此刻水平又上了一个台阶,掌握了用重定向测试程序。

8、修改,防越界,提交WA,参考他人代码http://blog.csdn.net/thudaliangrx/article/details/50699439进行手动对拍,发现一组奇葩测试数据:

77 1777
77/1777 = 0.(04333145751266178953292065278559369724254361283061...)
   1776 = number of digits in repeating cycle

马上对程序数组进行扩容int d[1000+10];变成int d[10000+10];提交AC。

9、很快又发现一组更奇葩的数据

77 2777
77/2777 = 0.(02772776377385667987036370183651422398271516024486...)
   2776 = number of digits in repeating cycle

程序出错,意识到AC不等于程序没问题,AC只是通过了网站的测试数据而已。

10、马上对程序数组进行扩容int d[10000+10];变成int d[20000+10];提交AC。同时解决了
77 2777
77/2777 = 0.(02772776377385667987036370183651422398271516024486...)
   2776 = number of digits in repeating cycle

11、本题失误在于,没想到有这么大的循环节,低估了测试数据的难度。

12、磕磕碰碰,不用对拍,还真没法解决问题,掌握了手动对拍。

13、附上AC代码,但有漏洞:

错误:

1111 1780
1111/1780 = 0.(62415730337078651685393258426966292134831460)
   44 = number of digits in repeating cycle

正确:

1111 1780
1111/1780 = 0.62(41573033707865168539325842696629213483146067)
   44 = number of digits in repeating cycle

无力再改,暂且搁置。

14、外出溜达一圈,突发灵感,判断连续的三个数是否有周期性,顺利解决上述问题,提交代码,继续AC。

附上代码

环境Dev-cpp4.9.9.2

#include <stdio.h>
int d[20000+10];//d[0]为整数部分,d[1]十分位,d[2]百分位,d[3]千分位......
int main(){
    int a,b;
    int count;
    int i,j,k,m;
    int flag;
    while(scanf("%d%d",&a,&b)!=EOF){
        count=0;
        printf("%d/%d ",a,b);
        while(a){//除法运算原理 
            d[count]=a/b;
            a=a%b;
            a*=10;
            count++;
            if(count==20000)
                break;
        }
        printf("= %d.",d[0]);//打印整数与小数点 
        if(a==0){
            for(i=1;i<count;i++)
                printf("%d",d[i]);
            printf("(0)\n");
            printf("   1 = number of digits in repeating cycle\n\n");
        }else{
            flag=0;
            for(i=1;i<count;i++){//寻找循环节 
                for(j=i+1;j<count;j++){
                    if(d[i]==d[j]){
                        k=j-i;//周期 
                        m=i;
                        if((j+2+3*k<count)&&(d[i]==d[j+k])&&(d[i]==d[j+2*k])&&(d[i]==d[j+3*k])&&(d[i+1]==d[j+1+k])&&(d[i+1]==d[j+1+2*k])&&(d[i+1]==d[j+1+3*k])&&(d[i+2]==d[j+2+k])&&(d[i+2]==d[j+2+2*k])&&(d[i+2]==d[j+2+3*k])){//验证周期是否正确,若不加上j+2+3*k<count会越界,出现Runtime error 
                            flag=1;
                            break;
                        }
                    }
                }
                if(flag)
                    break;
            }
            
            if(flag){
                for(i=1;i<m;i++)
                    printf("%d",d[i]);
                printf("(");
                if(k<=50){
                    for(i=m;i<m+k;i++)
                        printf("%d",d[i]);
                    printf(")\n");
                }else{
                    for(i=m;i<m+50;i++)
                        printf("%d",d[i]);
                    printf("...)\n");
                }
                printf("   %d = number of digits in repeating cycle\n\n",k);
            }
        }
        
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值