【题目链接】点击打开链接
【题目大意】
给出一个分数,输出它的循环小数表示。
【解题思路】
判断循环节。两个数组,一个数组yushu[]储存每一位的商,即小数点后面的数字。另一个数组vis[]储存每一次除法计算的商(或者被除数),当vis[]里某个元素访问两遍的时候,循环节出现,即从第一次出现该元素的位置到第二次出现该元素的位置。之后按格式输出即可。
【解题代码】
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn=3e4+5;
int vis[maxn];
int yushu[maxn];
int up,down;
int main()
{
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
int kcase=0;
while(~scanf("%d%d",&up,&down))
{
memset(vis,0,sizeof(vis));
memset(yushu,0,sizeof(yushu));
//输出相除的形式
printf("%d/%d = ",up,down);
//先输出整数部分
int circle=0;
int z=up/down;
yushu[0]=z;
int yu=up%down*10;
if(yu==0)//判断是否恰整除
{
printf("%d.(0)\n",z);
printf(" 1 = number of digits in repeating cycle\n");
continue;
}
else//不恰好整除
{
int i=1;
while(yu)//有限循环则退出
{
if(vis[yu])
{
circle=i-vis[yu];//i是当前位置,vis[yu]是上一次出现该被除数的位置。
break;
}
vis[yu]=i;
yushu[i]=yu/down;
i++;
yu=yu%down*10;
}
printf("%d.",yushu[0]);
if(!yu)
{
for(int j=1;j<i;j++)
printf("%d",yushu[j]);
printf("(0)\n 1 = number of digits in repeating cycle\n") ;
}
else//有循环节
{
int count=0;
for(int j=1;j<vis[yu];j++)
{
printf("%d",yushu[j]);
count++;
}
printf("(");
for(int j=vis[yu];j<i;j++)
{
if(count>=50)
{
printf("...");
break;
}
printf("%d",yushu[j]);
count++;
}
printf(")\n");
printf(" %d = number of digits in repeating cycle\n\n",circle);
}
}
}
return 0;
}
【收获与反思】
1.双数组来确定小数的循环节。
2.vis[]数组记录第一次出现某值的位置(同时也可检测是否出现过)。
3.UVa的输出格式比较较真,容易PE,这一题要求每一次输出后有一个空行(而非像其他UVa的题目要求每个答案间有一个空行),细心确认下即可。