【USACO 2.4.5】分数化小数

【描述】

写一个程序,输入一个形如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)

PROGRAM NAME fracdec

【格式】

INPUT FORMAT

单独的一行包括被空格分开的N和D(1 <= N,D <= 100000)。

OUTPUT FORMAT

按照上面规则计算出的小数表达式.如果结果长度大于76,每行输出76个字符.

【分析】

直接模拟除法就行了(长除法),不得不说有一点麻烦。

 1 #include <cstdlib>

 2 #include <iostream>

 3 #include <cstdio>

 4 #include <cstring>

 5 #include <cmath>

 6 #include <algorithm>

 7 const int maxn=1000000;

 8 using namespace std;

 9 int point=1,vis[maxn+100];//vis同时记录a在ans中的位置 

10 int ans[maxn],zf=0;//zf是字符输出统计 

11 void cnt();

12 int main()

13 {

14     int a,b,i;

15     //文件操作

16     freopen("fracdec.in","r",stdin);

17     freopen("fracdec.out","w",stdout);

18     memset(vis,0,sizeof(vis));//初始化

19      

20     scanf("%d%d",&a,&b);

21     if (a%b==0) {printf("%.1lf",(double)a/b);return 0;}//可以直接整除

22     

23     printf("%d.",a/b);cnt();

24     int temp=a/b;if (temp==0) cnt();

25     while (temp!=0) {cnt();temp/=10;}//顺便统计字符 

26     //printf(" %d\n",zf);

27     a=a%b;

28     vis[a]=1;

29     ans[point++]=a;

30     for (i=2;;i++)

31     {

32         a=(a*10)%b;

33         ans[point++]=a;

34         if (vis[a]) break;//出现重复值 

35         vis[a]=i;

36     }point--;

37     

38     for (i=1;i<vis[ans[point]];i++) {cnt();printf("%d",(ans[i]*10)/b);}//输出重复值之前的部分 

39     if ((ans[vis[ans[point]]]*10)/b==0 && vis[ans[point]]==point-1) return 0;//重复值为0 

40     cnt();printf("(");

41     for (i=vis[ans[point]];i<point;i++) {cnt();printf("%d",(ans[i]*10)/b);}

42     cnt();printf(")");

43     //printf("\n%d",zf);

44     return 0;

45 }

46 void cnt()

47 {

48      //已经输出了zf个字符 

49      if (zf==76) {printf("\n");zf=0;}

50      zf++;

51 }

 

你可能感兴趣的:(USACO)