题目描述:
写一个程序,输入一个形如N/D的分数(N是分子,D是分母),输出它的小数形式。 如果小数有循环节的话,把循环节放在一对圆括号中。
例如, 1/3 =0.33333333 写成0.(3), 41/333 = 0.123123123… 写成0.(123), 用xxx.0 等表示整数。 典型的转化例子:
1/3 = 0.(3)
22/5 = 4.4
1/7 = 0.(142857)
2/2 = 1.0
3/8 = 0.375
45/56 = 0.803(571428)
INPUT FORMAT
单独的一行包括被空格分开的N和D(1 <= N,D <= 100000)。
SAMPLE INPUT
45 56
OUTPUT FORMAT
按照上面规则计算出的小数表达式.如果结果长度大于76,每行输出76个字符.
SAMPLE OUTPUT
0.803(571428)
解题思路:
模拟人工除法,用一个hash数组保存余数第一次出现的位置即可,如果再次出现则代表有循环。这题就是小的坑比较多,写的时候就会发现,例如第一次整数相除的位数会影响76个字符的长度等,如果思路严谨的话应该是不会踩坑的。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
FILE *fout;
int hash[1000010]; //记录余数出现的位置
int ans[1000010];
int N,D;
int step=0;//记录答案位数
int pre=-1,pro=-1;//记录循环开始的位置和结束的位置
int length=0;//记录数据长度
void judge(){//判断是否超76个字符
length++;
if(length%76==0){
fprintf(fout,"\n");
length=0;
}
}
int main(){
FILE *fin = fopen ("fracdec.in", "r");
fout = fopen ("fracdec.out", "w");
fscanf(fin,"%d%d",&N,&D);
while(1){
ans[step]=N/D;
if(N%D==0){
break;
}else{
if(hash[N%D]>=1){
pre=hash[N%D]+1;
pro=step;
while(ans[pre-1]==ans[pro]){
pre--,pro--;step--;
}
break;
}else{
hash[N%D]=step;
N=N%D*10;
step++;
}
}
}
if(step==0)step++;//如果为整数则小数输出0
int temp=ans[0];//计算整数部分的位数,如果大于一位则增加长度
while(temp>0){
temp/=10;
length++;
}
if(ans[0]>0)
length--;
for(int i=0;i<=step;i++){//输出答案
if(i==1){
fprintf(fout,".");
judge();
}
if(i==pre){
fprintf(fout,"(");
judge();
}
fprintf(fout,"%d",ans[i]);
judge();
if(i==pro){
fprintf(fout,")");
judge();
break;
}
}
fprintf(fout,"\n");
exit(0);
}