AC链接:http://poj.org/problem?id=3101
原博客:http://blog.csdn.net/huayunhualuo/article/details/51055611
感觉应该记录一下的题目。
题意:已知n个行星和每一个行星的周期Ti,求所有行星共线的最短的周期。
分析:每一个行星的角速度为vi=2πTi,选择行星0为参考点(所有行星均以其为参考点),则相对于行星0的角速度为v′i=2πTi−T0TiTo,则i行星相对0行星转动半圈的时间为T′i=πv′i=TiT02(Ti−T0)问题就转化为求T′1,T′2,T′3⋯,T′n−1的最小公倍数最小公倍数:对于整数的最小公倍数为LCM(a,b)=a×bGCD(a,b),那么对于分数呢?结论:LCM(ab,cd)=LCM(a,c)GCD(b,d)证明:假设mn是ab,cd的最小公倍数,那么mn×ba=N,mn×dc=N′显然m是a,c的倍数,n是b,d的约数,由于是最小公倍数,那么自然是m尽量的小,n尽量的大。所以m=LCM(a,c),n=GCD(b,d)。由于数据的结果比较的大,所以用高精度算法或者是Java。
代码:
import java.math.*;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner cin=new Scanner(System.in);
int i,n,num;
int[] tmp=new int[1005];
int[] t=new int[1005];
n=cin.nextInt();
for(i=0;i<n;i++)
tmp[i]=cin.nextInt();
//去重
Arrays.sort(tmp,0,n);
num=0;t[0]=tmp[0];
for(i=1;i<n;i++) //t下标从0到num
{
if(tmp[i]!=tmp[i-1])
t[++num]=tmp[i];
}
BigInteger a,b,gc,up=null,down=null; //up是分子,down分母,gc是分子分母的最大公约数用来约分
for(i=1;i<=num;i++)
{
a=BigInteger.valueOf(t[i]*t[0]);
b=BigInteger.valueOf((t[i]-t[0])*2);
gc=a.gcd(b);
if(i==1) //如果处理到第二颗行星,此时得到第一个分式,直接约分
{
up=a.divide(gc);
down=b.divide(gc);
}else{ //如果此时是在求分式的LCM,那么此时的up,down,a,b分别一一对应公式LCM(a/b,c/d)中的a,b,c,d
a=a.divide(gc);
b=b.divide(gc);
up=up.multiply(a).divide(up.gcd(a)); //up=(up*a)/(gcd(up,a))
down=down.gcd(b); //down=gcd(down,b);
}
}
System.out.println(up+" "+down);
cin.close();
}
}