USACO-Section2.4 Fractions to Decimals【模拟法】

题目描述:

写一个程序,输入一个形如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);    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值