csu 1303 Decimal (数论题)
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1303
1303: Decimal
Time Limit: 1 Sec Memory Limit: 128 MB Submit: 589 Solved: 61 [Submit][Status][Web Board]Description
任意一个分数都是有理数,对于任意一个有限小数,我们都可以表示成一个无限循环小数的形式(在其末尾添加0),对于任意一个无限循环小数都可以转化成一个分数。现在你的任务就是将任意一个无限循环小数转化成既约分数形式。所谓既约分数表示,分子和分母的最大公约数是1。
Input
有多组数据。
每组数据一行。输入为0.a1a2a3...ak(b1b2...bm)的形式,其中a1a2a3...ak为非循环部分,(b1b2b3..bm)为循环部分。数据保证非循环部分的长度k和循环部分的长度m不会超过8.
Output
对于每组测试数据输出A/B,其中A是分子,B是分母,A,B均为整数。
Sample Input
0.0(714285) 0.0(5) 0.9(671)
Sample Output
1/14 1/18 4831/4995
【题解】:
分成两部分求解:
第一部分非循环部分,这部分很好求:(非循环部分)/ (非循环位数*10) 例如:0.3 == 3/10
第二部分为循环部分,(循环部分)/ (循环位数*10-1) 例如: 0.(3) == 3/(10-1) == 1/3
当然像 0.1(3)这种既有非循环又有循环的,就通过两部分想加就行
要注意的是:循环部分为 (循环部分)/ ((循环位数*10-1)* (非循环位数*10))
【code】:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 6 using namespace std; 7 8 char str[100]; 9 10 long long gcd(long long u,long long v) 11 { 12 long long temp=u; 13 if(u>v) temp=u,u=v,v=temp; 14 while(temp) 15 { 16 temp = v%u; 17 v=u; 18 u=temp; 19 } 20 return v; 21 } 22 23 int main() 24 { 25 long long arr[]={1,10,1e2,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12}; 26 while(~scanf("%s",str)) 27 { 28 int i,f_cnt=0,x_cnt=0,flag = 0; 29 long long s1=0,s2=0; 30 int len = strlen(str); 31 for(i=0;i<len;i++) 32 { 33 char ch = str[i]; 34 if(ch=='(') //取括号里面的循环部分 35 { 36 i++; 37 while(i<len&&isdigit(str[i])) 38 { 39 s2=10*s2+str[i]-'0'; 40 x_cnt++; //循环位数计算 41 if(i+1>=len||!isdigit(str[i+1])) break; 42 i++; 43 } 44 flag=0; 45 } 46 if(flag) //小数点后面的非循环部分 47 { 48 while(i<len&&isdigit(str[i])) 49 { 50 s1=10*s1+str[i]-'0'; 51 f_cnt++; //非循环位数计算 52 if(i+1>=len||!isdigit(str[i+1])) break; 53 i++; 54 } 55 } 56 if(ch=='.') 57 { 58 flag = 1; //标记小数点的出现 59 } 60 } 61 //非循环部分 s1 / arr[f_cnt] 62 //循环部分 s2 / (arr[x_cnt-1]-1) * (1 / arr[f_cnt]) 63 if(x_cnt==0) arr[x_cnt]=10; //排除当x_cnt为0时 arr[cnt]-1出现除数为0的情况 64 long long up = s1*(arr[x_cnt]-1)+s2; 65 long long down = (arr[x_cnt]-1)*arr[f_cnt]; 66 long long temp = gcd(up,down); 67 if(x_cnt==0) arr[x_cnt]=1; //记得改过来 68 printf("%lld/%lld\n",up/temp,down/temp); 69 } 70 return 0; 71 }