EOJ 2980. 小数转化分数
2980. 小数转化分数
题目:
给定一个正有理数A(A>0),输出 A的最简分数形式。
输入格式
第 1行:一个整数 T(1<=T<=10) 为问题数。
第2~T+1行:每行有一个字符串(字符串长度不超过),表示有理数。字符串中只包含三类字符:0~9,.,[,],在 [和 ] 之间的数字表示循环小数的循环节,例如:0.[6]表示有理数
输出格式
对于每个问题,输出一行问题的编号( 开始编号,格式:case #0: 等),然后在一行中输出 的最简分数形式,行末尾输出一个换行符。具体输出格式见样例。
样例
input
4
0.5
0.[6]
11.0[8]
1.[142857]
output
case #0:
1/2
case #1:
2/3
case #2:
499/45
case #3:
8/7
思路
无循环小数:gcd
纯循环小数:一个循环节有几个数,分母就有几个9,分子则为一个循环节上的数
例.0.[7]=7/9, 0.[114514]=114514/999999
混循环小数,循环节有几个数,分母就有几个9,不循环的有几个数,分母再添几个0,分子是从不循环到一个循环节数减去不循环的数
例.0.114[514]=(114514-114)/999000, 0.1[14514]=(114514-1)/999990
&
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
int ti, ret = 0;
cin >> ti;
while (ti--)
{
printf("case #%d:\n", ret++);
string a;
string b;
unsigned long long fenzi = 0, fenmu = 0;//终极杀器u64,让数据不再溢出
cin >> a;
int t = a.find('.');
unsigned long long sumz = 0; //整数部分;
for (int i = 0; i < t; i++)
{
sumz = sumz * 10 + (a[i] - '0');
}
int cl = a.find('['); //左括号
int cr = a.find(']'); //右括号
if (cl != -1) //循环小数部分
{
if (cl - t == 1)
{
for (int i = cl + 1; i < cr; i++)
{
fenzi = fenzi * 10 + (a[i] - '0');
}
int mo = cr - cl - 1;
while (mo--)
{
fenmu = fenmu * 10 + 9;
}
} //全段循环直接是循环段做分子,循环位个9做分母
else
{
int po = cl - t - 1;
int mo = cr - cl - 1;
int temp = mo;
while (mo--)
{
fenmu = fenmu * 10 + 9;
}
for (int i = cl + 1; i < cr; i++)
{
fenzi = fenzi * 10 + (a[i] - '0');
}
unsigned long long quan = 0;
for (int i = t + 1; i < cl; i++)
{
quan = quan * 10 + (a[i] - '0');
}
unsigned long long quan2 = quan;
while (po--)
{
fenmu *= 10;
}
while (temp--)
{
quan2 *= 10;
}
// cout << fenzi << " " << quan << " " << quan2 << endl;
fenzi = quan2 - quan + fenzi;
}
fenzi = fenzi + sumz * fenmu;
long long tui = __gcd(fenzi, fenmu); //__gcd函数求最大公约数
cout << fenzi / tui << "/" << fenmu / tui << endl;
} //部分循环,前继段和循环段组成的数减去一份前继段组成数做分子,循环段长个9加前继段长个0做分母
else
{
b.assign(a.rbegin(), a.rend());
int thy = b.find('.');
fenmu = 1;
for (int i = t + 1; i < t + thy + 1; i++)
{
fenzi = fenzi * 10 + a[i] - '0';
}
while (thy--)
{
fenmu *= 10;
}
fenzi += sumz * fenmu;
unsigned long long tui = __gcd(fenzi, fenmu); //__gcd函数求最大公约数
cout << fenzi / tui << "/" << fenmu / tui << endl;
}
}
}
//总结:有了gcd,化简不是问题
//本人博客https://www.cnblogs.com/emokable/
//时间:2022/4/13