POJ 1930(模拟+思维)

题意

给一个小于1大于0的无限循环小数,将其化成分数,输出分母最小的情况。

分析

首先题目给定了数字最长是9位,组成是0.abcde…这样的形式,所以可以直接读取中间的数字并用ll存起来。然后遍历9种循环情况,分别求出他们的分数形式。下面说下如何化成分数。

隐约记得这个是小学课本上的东西,首先将这个数乘pow(10,循环节的长度),然后减去这个整数,举个例子,0.923333…这里我们假设3是循环节,那么乘以10,得到9.233下发现后面的循环的3都被减去了,那么只剩下9.23和0.92。同理假设循环节是23,那么就乘上100,得到92.3232323…另一个还是0.92323,对比一下发现后面的23也都减去了,剩下也只剩92.3-0.9。但是小数不好处理,所以我们直接用整数处理以后再化成小数。首先我们得到的是整个数字部分的整数,然后遍历每个循环节,假设循环节是后1位,后两位…后i位..这样循环节的长度就是i,所以先乘以的数就是pow(10,i)然后再减去这个数。因为先乘了pow(10,i),又减去了1,所以最后还要除pow(10,i)-1.然后分子和分母单独看,求个gcd,遍历每种循环节情况,输出最小分母的那一种。

这里有个细节问题,因为我们处理的时候是整数,但实际上应该是小数,所以再做除法的时候要分母不一定是上述的pow(10,i),还需要乘上一个倍数。具体看代码

代码

#include 
#include 
#include 
#include 
using namespace std;
typedef long long int ll;
ll gcd(ll a, ll b)
{
    if (a > b) swap(a, b);
    if (a == 0) return b;
    else return gcd(b%a, a);
}
int main()
{
    ios::sync_with_stdio(false);
    string a;
    while (cin >> a&&a!="0")
    {
        ll all = 0;
        for (int i = 2; a[i] != '.'; i++)
        {
            all += a[i] - '0';
            all = all * 10;
        }
        all = all / 10;
        int len = a.size() - 5;
        ll up, down, g, mu = 100000000000, md = 100000000000;
        for (int i = 1; i <= len; i++)
        {
            up = all - all / (ll)pow(10.0, i);
            down = ((ll)pow(10.0, i) - 1)*(ll)pow(10.0, len - i);
            g = gcd(up, down);
            if (down / g < md) { md = down / g; mu = up / g; }
        }
        cout << mu << "/" << md << endl;
    }
}

你可能感兴趣的:(模拟)