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 <iostream>
#include <string>
#include <cmath>
#include <algorithm>
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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值