POJ 1930 循环小数化分数

Dead Fraction
Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 4100 Accepted: 1382
Description

Mike is frantically scrambling to finish his thesis at the last minute. He needs to assemble all his research notes into vaguely coherent form in the next 3 days. Unfortunately, he notices that he had been extremely sloppy in his calculations. Whenever he needed to perform arithmetic, he just plugged it into a calculator and scribbled down as much of the answer as he felt was relevant. Whenever a repeating fraction was displayed, Mike simply reccorded the first few digits followed by “…”. For instance, instead of “1/3” he might have written down “0.3333…”. Unfortunately, his results require exact fractions! He doesn’t have time to redo every calculation, so he needs you to write a program (and FAST!) to automatically deduce the original fractions.
To make this tenable, he assumes that the original fraction is always the simplest one that produces the given sequence of digits; by simplest, he means the the one with smallest denominator. Also, he assumes that he did not neglect to write down important digits; no digit from the repeating portion of the decimal expansion was left unrecorded (even if this repeating portion was all zeroes).
Input

There are several test cases. For each test case there is one line of input of the form “0.dddd…” where dddd is a string of 1 to 9 digits, not all zero. A line containing 0 follows the last case.
Output

For each case, output the original fraction.
Sample Input

0.2…
0.20…
0.474612399…
0
Sample Output

2/9
1/5
1186531/2500000

数论解释(找了好多个,才看懂的解释)
一、0.abcdefg…
不循环部分(abcd)长度为c,循环部分(efg)长度为k
若此循环小数可化成a/b的形式
则10^(k+c)a/b=abcdef.000000
10^c
a/b=abcd.efg…
两式相减得
10^(k+c)a/b -10^ca/b=abcdef.000000 - abcd.efg…
设abcdef为all abcd为num
化简第三式得
a/b=all-num/10c*(10k-1)
因此只需计算出右边分子分母

二、
纯循环小数
分子是循环节
分母是n个9

混循环小数
一个循环节的长度为n,不循环的部分为m
分母是n个9拼上m个0
分子是不循环部分和一个循环节拼起来的数减去不循环部分

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <fstream>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
 
using namespace std;
#define   maxn          1010
#define   lson          l,m,rt<<1
#define   rson          m+1,r,rt<<1|1
#define   ms(x,y)      memset(x,y,sizeof(x))
#define   rep(i,n)      for(int i=0;i<(n);i++)
#define   repf(i,a,b)   for(int i=(a);i<=(b);i++)
#define   PI           pair<int,int>
//#define   mp            make_pair
#define   FI            first
#define   SE            second
#define   IT            iterator
#define   PB            push_back
#define   Times         10
typedef   long long     ll;
typedef   unsigned long long ull;
typedef   long double   ld;
typedef   pair<int ,int > P;
//#define N 100
const double eps = 1e-10;
const double  pi = acos(-1.0);
const  ll    mod = 1e9+7;
const  int   inf = 0x3f3f3f3f;
const  ll    INF = (ll)1e18+300;
const int   maxd = 51000 + 10;
 
bool judge_zero(string s) {
    for (int i = 2; i < s.length(); i++) {
        if(s[i] != '0') {
            return false;
        }
    }
    return true;
}
 
int gcd(int a,int b) {
    if(!b) {
        return a;
    }
    else return gcd(b, a%b);
}
int main() {
    string s;
    while(cin >> s) {
        if(s.length() == 1 && s[0] == '0') {
            break;
        }
        if(judge_zero(s)) {
            cout << "0/1\n" << endl;
            continue;
        }
        int len = s.length();
        ll res = 0;
        int num = 0;
        for (int i = 2; i < len; i++) {
            if(s[i] == '.') {
                break;
            }
            num ++ ;
            res = res * 10 + s[i] - '0';        //将小数部分化整 
        }
        int min_fz = inf, min_fm = inf;         //const  int   inf = 0x3f3f3f3f;
        //cout << res << endl;
        for (int cnt = res, k = 1, i = 1; i <= num; i ++) {
            cnt /= 10;
            int a = res - cnt;
            k *= 10;
            int l = num - i;
            int cns = res - cnt;      //分子 
            int ans = (int)pow(10.0, l) * (pow(10.0, i) - 1);   //分母 
            int com = gcd(cns, ans);         //最大公约数 化简分数 
            if(ans / com < min_fm) {
                min_fz = cns / com;
                min_fm = ans / com;
            }
        }
        cout << min_fz << "/" << min_fm << endl;
    }
    return 0; 
}
发布了22 篇原创文章 · 获赞 33 · 访问量 1082

猜你喜欢

转载自blog.csdn.net/qq_42577542/article/details/89608964