【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 }