poj 3101 Astronomy——求分数的最小公倍数
已知n个点的环绕点X的周期,求出各点转到同一直线上的最短时间。
求出相邻点间相距半圈所需时间=追及时间/2。求出各个半圈时间的最小公倍数为结果
公式:T[i] = d[i]*d[i+1] / (d[i+1]-d[i])*2
那么以读入的第一个点为基准点,求出以后所有点和第一个点相聚半圈所需的时间,求出这几个分数的最小公倍数就可以了。(和第一个点所用的时间相同就不用计算了)
分数的最小公倍数求法:设两分数为a/b,c/d(已化为最简形式),则最小公倍数为:lcm(a,c)/gcd(b,d)
所以在每读一个周期的时候先把公式化为最简形式,再分别对分子分母求lcm和gcd
a27400 | 3101 | Accepted | 5452K | 3344MS | Java | 1616B | 2011-09-07 12:41:57 |
import java.io.BufferedInputStream;
import java.util.*;
import java.math.*;
public class Main
{
public static int[] p=new int[3000];
public static int top;
public static int[] a=new int[3000];
public static boolean[] isprime=new boolean[10001];
public static void init()
{
int i,j;
for(i=2;i<=10000;i++)
{
if(!isprime[i]) p[top++]=i;
for(j=0;j<top&&i*p[j]<=10000;j++)
{
isprime[i*p[j]]=true;
if(i%p[j]==0) break;
}
}
top--;
isprime[1]=true;
}
public static void solve(int k)
{
for(int i=0;i<=top&&p[i]<=k;i++)
{
int temp=0;
while(k%p[i]==0)
{
temp++;
k/=p[i];
}
if(temp>a[i])
a[i]=temp;
}
}
public static int gcd(int x1,int x2)
{
if(x2==0)
return x1;
return gcd(x2,x1%x2);
}
public static void main(String[] args)
{
Scanner cin=new Scanner(new BufferedInputStream(System.in));
init();
int n=cin.nextInt();
int[] q=new int[1000];
int[] sub=new int[1000];
q[0]=cin.nextInt();
for(int i=1;i< n;i++)
{
q[i]=cin.nextInt();
int temp=Math.abs(q[i]-q[0]);
if(temp!=0)
{
int Gcd=gcd(q[i]*q[0],temp);
temp=temp/Gcd;
sub[i]=temp;
solve(q[i]*q[0]/Gcd);
}
}
BigInteger ans1=BigInteger.ONE;
for(int i=0;i<=top;i++)
for(int j=0;j<a[i];j++)
ans1=ans1.multiply(BigInteger.valueOf(p[i]));
int ans2=0;
for(int i=1;i< n;i++)
ans2=gcd(ans2,sub[i]);
if(a[0]>0)
ans1=ans1.divide(BigInteger.valueOf(2));
else ans2*=2;
if(ans2==0)
ans1=BigInteger.ZERO;
System.out.println(ans1+" "+ans2);
}
}