POJ3101 分数的最小公倍数

   这个题怎么说呢?像是高中物理题吧, 选一个W0 = 2*pi/t0,作为参考系, 则Wi=2*pi/ti, Wx = Wi - W0 = 2*pi*(t0-ti)/t0*ti;  则相对半圈时间是tbi = t0*ti/2*(t0-ti);     对于所有的tbi(i>=1), 我们找到一个时间T,使这个时间可以整除所有的tbi, 最后使这个T最小,那么T就是这个答案。根据上面的分析得知我们要求得T就是tbi的最小公倍数。。代码如下:

 

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>

using namespace std;
int n;
int t[1024], r[1000];
int fz[10000 + 100];



int gcd(int a, int b)
{
    if(b==0) return a;
    else return gcd(b, a%b);
}

void multi(int d)                   //高精度乘法
{
    int tmp = 0;
    for(int i=0; i<1000; i++)
    {
        r[i] = r[i]*d + tmp;
        tmp = r[i]/10000;
        r[i] %= 10000;
    }
}

int main()
{
    while(scanf("%d", &n) == 1)
    {
        memset(fz, 0, sizeof(fz));
        for(int i=0; i<n; i++)
            scanf("%d", &t[i]);
        sort(t, t+n);
        n = unique(t, t+n) - t;
        int fm = 0;
        for(int i=1; i<n; i++)
        {
            int a = t[0]*t[i];
            int b = 2*abs(t[0]-t[i]);
            int c = gcd(a, b);
            a /= c;
            b /= c;                         //      a / b
            fm = gcd(b, fm);

            for(int i=2; i<10000; i++)
            {
                int k = 0;
                while(a%i == 0)
                {
                    k++;
                    a/=i;
                }
                if(k > fz[i]) fz[i] = k;
                if(a == 1) break;
            }
        }
        memset(r, 0, sizeof(r));
        r[0] = 1;
        for(int i=2; i<10000; i++)
            for(int j=0; j<fz[i]; j++)
                multi(i);
        int i = 999;
        while(r[i]==0) i--;
        printf("%d", r[i]);
        for(int k=--i; k>=0; k--) printf("%04d", r[k]);  //注意高精度输出啊, wa了几发
        printf(" ");
        printf("%d\n", fm);
    }
    return 0;
}

 

posted @ 2015-11-14 10:32  xing-xing  阅读(210)  评论(0)    收藏  举报