【算法竞赛入门经典】习题3-8循环小数(Uva202)

一、题目

偷个懒,题目在这里Uva202
大意就是输入两个整数a和b,输出a/b的循环小数表示以及循环节的长度。

二、解题思路

关键在于找循环节,用res来存储每一次的商,用mod数组来存储每一次的余数。在计算小数部分时每次都将上一次的余数乘十作为本次的被除数,依次进行下去直到找到某一次的商和余数在前面出现过,即找到了循环节。
要注意输出的格式,每个用例最后应该有两个换行符
具体见代码及注释

三、代码

#include<stdio.h>
int res[3005],mod[3005];//res数组记录每一次的商,mod数组记录每一次的余数 
int main(){
 int a,b;
 while(scanf("%d%d",&a,&b)!=EOF){
  int i=0,j;
  int flag=0;//标记是否找到了循环节 
  printf("%d/%d = %d.",a,b,a/b);//先输出整数部分 
  while(true){
   res[i]=a/b;
      mod[i]=a%b;
      a=(a%b)*10; //将这次的余数乘以十作为下一次的被除数 
      for(j=1;j<i;j++){  //与前面出现的商和余数进行比较;注意是从j=1,即小数点后进行比较 
       if((res[j]==res[i]) && (mod[j]==mod[i])){ //若余数和商的组合在前面出现过,则表示出现循环节 
        flag=1; //此时的i为第二次出现循环节的开头第一个数字的位置 
        break;
    }
   }
   if(flag){
    break;
   }
   i++;
  }
  for(int k=1;k<j;k++){ //注意到res[0]中存储的是整数部分 
   printf("%d",res[k]); //输出小数点后非循环节部分 
  }
  printf("(");
  if(i>50){ //如果要输出的小数部分位数大于50,就只输出前50个 
   for(int k=j;k<=50;k++){
    printf("%d",res[k]);
   }
   printf("...)\n");
  }else{
   for(int k=j;k<i;k++){
    printf("%d",res[k]);
   }
   printf(")\n");
  }
  printf("   %d = number of digits in repeating cycle\n\n",i-j); //注意输出格式,循环节长度前有三个空格,末尾两个换行符 
 }
 return 0;
}
发布了91 篇原创文章 · 获赞 28 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/gyx1549624673/article/details/103207937