nocow已经瘫痪两三天了。又不想复习就只能去做杭电的step了,以前做了一点点。这次做的是小数化为分数,因为以前已经做过一个化无限循环的小数为分数的题目了,还有印象所以这个相对来说并不是很难。不过一开始超时,估计是约分写得不行。后来改成了用辗转相除法求最大公约数然后再约分就好了。还有就是要注意有时候数据会超限的。所以要先约分再通分而且通分的时候不能直接乘,要通过求最小公倍数来通分。
题目链接:http://acm.hdu.edu.cn/game/entry/problem/show.php?chapterid=2§ionid=1&problemid=12
大体思路:把循环部分和不循环的部分分开计算,然后加起来就可以了。
代码:
#include <iostream>
using namespace std;
int a, b, c, d;
int len;
int gcd (int xx, int yy){
return yy == 0? xx : gcd(yy, xx % yy);
}
/*void YF(int &x, int &y){
while(x % 2 == 0 && y % 2 == 0){
x /= 2;
y /= 2;
}
for(int i = 3; i <= x; i += 2){
while(x % i == 0 && y % i == 0){
x /= i;
y /= i;
}
}
}
*/
void trans1(char *s){
a = 0, b = 1;
if(s[0] == '\0')
return ;
for(int i = 0; s[i] != '\0'; ++i)
{
a = a * 10 + s[i] - '0';
b *= 10;
}
//YF(a, b);
}
void trans2(char *s){
c = 0, d = 1;
if(s[0] == '\0')
return ;
int i;
for(i = 0; s[i] != '\0'; ++i){
c = c * 10 + s[i] - '0';
d *= 10;
}
--d;
//YF(c, d);
while(len--)
d *= 10;
}
void ADD(){
int tmp;
tmp = gcd(c, d);
c /= tmp, d /= tmp;
tmp = gcd(a, b);
a /= tmp, b /= tmp;
if(a == 0){
cout << c << '/' << d << endl;
return ;
}
else if(c == 0){
cout << a << '/' << b << endl;
return ;
}
tmp = gcd(d, b);
tmp = d / tmp * b;
a = a * (tmp / b) + c * (tmp / d);
b = tmp;
tmp = gcd(a, b);
cout << a / tmp << '/' << b / tmp << endl;
}
int main(){
int n;
char s[50];
while(cin >> n){
while(n--){
cin >> s;
char s1[50] = {'\0'}, s2[50] = {'\0'};
int i = 2, j = 0;
for(i = 2, j = 0; s[i] != '\0'; ++i){
if(s[i] == '(')
break;
s1[j++] = s[i];
s1[j] = '\0';
}
len = i - 2;
if(s[i] == '('){
for(++i, j = 0; s[i] != ')'; ++i){
s2[j++] = s[i];
s2[j] = '\0';
}
}
trans1(s1);
trans2(s2);
ADD();
}
}
return 0;
}