《挑战程序设计竞赛》2.6 数学问题-辗转相除法 AOJ0005 POJ2429 1930(1)
AOJ0005
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0005
题意
给定两个数,求其最大公约数GCD以及最小公倍数LCM。
思路
求最大公约数一般用辗转相除法,然后就得到了最小公倍数。 
更详细的分析参见我的博客文章: 
数论——最大公约数和最小公倍数算法
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
unsigned GCD(unsigned a, unsigned b)
{
    if (!b) return a;
    return GCD(b, a%b);
}
unsigned LCM(unsigned a, unsigned b)
{
    return a / GCD(b, a-b) * b;
}
int main(void)
{
    unsigned a, b;
    while (scanf("%u %u", &a, &b) != EOF) {
        if (a < b) swap(a, b);
        printf("%u %u\n", GCD(a, b), LCM(a, b));
    }
    return 0;
}POJ2429
POJ1930
http://poj.org/problem?id=1930
题意
将一个无限循环小数转化成分母最小的精确分数值。 
注意:循环的部分不一定是最后一位,有可能从小数点后面全是循环部分。
思路
将分数分成循环的部分和非循环的部分: 
设分数为0.i1 i2 i3 i4 .. ik j1 j2 j3 .. jc,其中i1 ~ ik 为非循环的部分,j1 ~ jc为循环部分。 
非循环的部分可以拆成 b / a 其中 b = ( i1…ik)   a = 10 ^ (k); 
循环的部分可以拆成  bb / aa 其中 bb = (j1 .. jc)  aa = 10 ^ (k + c) - 10 ^ ( k); 
则所求分数为 b / a + bb / aa,通分得 (b * aa + bb * a) / a * aa,约分得答案(用最大公约数求)。 
另外,据说数据会有全是0的坑爹数据,但我没有被坑到。
代码
Source Code
Problem: 1930       User: liangrx06
Memory: 172K        Time: 16MS
Language: C++       Result: Accepted
Source Code
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <algorithm>
using namespace std;
int gcd(int a, int b)
{
    if (b == 0)
        return a;
    return gcd(b, a%b);
}
int exp10(int x)
{
    int res = 1;
    while (x--)
        res *= 10;
    return res;
}
int main(void)
{
    int i, j, a, b, a10, b10, g, len;
    int m, n;
    string s, sa, sb;
    while(cin >> s)
    {
        if(s == "0")
            break;
        len = s.size();
        for(i = 1; i <= len-5; i++) {
            sa = s.substr(len-3-i, i);
            a = atoi(sa.c_str());
            a10 = exp10(i);
            j = len-5-i;
            sb = s.substr(2, j);
            b = atoi(sb.c_str());
            b10 = exp10(j);
            int tn = (a10-1)*b10;
            int tm = b*(a10-1) + a;
            g = gcd(tn, tm);
            tn /= g;
            tm /= g;
            if (i == 1 || i > 1 && tn < n) {
                n = tn;
                m = tm;
            }
        }
        printf("%d/%d\n", m, n);
    }
    return 0;
}
    编程算法爱好者。
 
                    
                     
                    
                 
                    
                 
                
            
         
 
         浙公网安备 33010602011771号
浙公网安备 33010602011771号