1. 程式人生 > >HDU 1717 小數化分數2(數學基本知識)

HDU 1717 小數化分數2(數學基本知識)

Sample Output
4/9
1/2
17/52

【思路分析】
  該題的關鍵點就是迴圈小數化為分數,有一個結論,假如這個迴圈小數是0.(1234),其化為分數即為1234/9999,也就是迴圈的部分除以這個迴圈部分長度個9,即1234除以4個(1234的長度)9。證明如下:
  設這個迴圈小數x為0.(yyy),將這個x乘以10的迴圈長度的次方,即10^3,得到yyy.(yyy),從而可以得出下列等式:
x*10^3 - x = yyy  =>  x(10^3 - 1) = yyy  =>  x = yyy/999。其他長度同理可證。
  有了以上的結論便可以將迴圈小數化為分數。然後由gcd求出最大公約數對分數化簡。
  還有一點需要注意的就是這個小數包括不迴圈小數和迴圈小數兩個部分,則需要分別對這兩個部分化為分數,然後再相加、通分、合併、化簡。這個過程需要注意通分後的資料範圍,由於小數位數最長為9,所以通分時int會存不下這個結果,因此需要用long long 或者_int64 的變數來存結果,否則會報WA。

程式碼如下:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
__int64 gcd(__int64 a,__int64 b)
{
    __int64 r = 1;
    while (r > 0)
    {
        r = a % b;
        a = b;
        b = r;
    }
    return a;
}
int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        char num[20];
        scanf("%s",num);
        int len = strlen(num);
        int i;
        __int64 a = 0,b = 0;//a記錄不迴圈的小數部分,b記錄迴圈的小數部分
        int lenofA = 0,lenofB = 0;//a的長度和b的長度
        __int64 div1 = 1,div2 = 0;//不迴圈小數和迴圈小數的對應的分母

        for(i = 2;i < len;i++)//存取不迴圈小數
        {
            if(num[i] != '(')
            {
                a *= 10;
                a += num[i] - '0';
                lenofA++;
                div1 *= 10;
            }
            if(num[i] == '(')
                break;
        }
        i++;
        while(i < len)//存取迴圈小數
        {
            if(num[i] != ')')
            {
                b *= 10;
                b += num[i] - '0';
                lenofB++;
                div2 *= 10;
                div2 += 9;
            }
            i++;
        }

        if(lenofA != 0)
            div2 *= div1;
        int gcd1,gcd2;
        if(a == 0 && b != 0)//不存在不迴圈小數部分
        {
            gcd2 = gcd(b,div2);
            b /= gcd2;
            div2 /= gcd2;
            printf("%I64d/%I64d\n",b,div2);
        }
        if(b == 0 && a != 0)//不存在迴圈小數部分
        {
            gcd1 = gcd(a,div1);
            a /= gcd1;
            div1 /= gcd1;
            printf("%I64d/%I64d\n",a,div1);
        }
        if(a != 0 && b != 0)
        {
            gcd1 = gcd(a,div1);
            gcd2 = gcd(b,div2);
            a /= gcd1;
            div1 /= gcd1;
            b /= gcd2;
            div2 /= gcd2;
            __int64 top = a * div2 + b * div1;
            __int64 down = div1 * div2;
            __int64 gcd3 = gcd(top,down);
            top /= gcd3;
            down /= gcd3;
            printf("%I64d/%I64d\n",top,down);

        }

    }
    return 0;
}