习题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;
}