poj 3101Astronomy(圆周追击+分数最小公倍数)

  1 /*
  2    本题属于圆周追击问题:
  3      假设已知两个圆周运动的物体的周期分别是a ,b, 设每隔时间t就会在同一条直线上 
  4      在同一条直线上的条件是 角度之差为 PI !
  5      那么就有方程 (2PI/a - 2PI/b)* t=PI  所以就有 t=ab/(2|a-b|);
  6      如果有多个物体, 就会有多个t值,所以每隔 所有 t值的最小公倍数的时间所有的物体就会在同一直线上!
  7      
  8      另外:如果分数的分子分别是 a1, a2, ...., 和 b1, b2, ....
  9      那么所有分数的最小公倍数就是lcm(a1, a2, ...)/gcd(b1, b2,....);
 10      
 11      再有:如何求多个数的最小公倍数呢?
 12      根据数论,每一个数都可以表示成素数的乘积的形式! 
 13      令p[i]存储素数,将a1,a2,...分别整除以p[i],直到除尽!并记录除以每个p[i]时的个数temp;
 14      并更新该个数的最大值cnt[i]=max(temp, cnt[i]); 
 15      
 16      最后cnt[i]个p[i]分别相乘得到最终的结果就是所有数的最小公倍数! 
 17 */
 18 #include<iostream>
 19 #include<cstring>
 20 #include<cmath>
 21 #include<cstdio>
 22 #define M 10005
 23 #define N 1005
 24 using namespace std;
 25 typedef long long LL;
 26 LL p[M];
 27 bool isP[M];
 28 LL cnt[M];
 29 LL q[N];
 30 LL ans[N], endx;
 31 LL top;
 32 
 33 void bigN(){//大数据的处理
 34    LL c=0;
 35    endx=0;
 36    ans[0]=1;
 37    for(LL i=0; i<top; ++i)
 38       for(LL j=0; j<cnt[i]; ++j){
 39           for(LL k=0; k<=endx; ++k){
 40              ans[k]=ans[k]*p[i] + c;
 41              c=ans[k]/10000;
 42              ans[k]%=10000;
 43           }
 44           if(c>0){
 45              ans[++endx]=c;
 46              c=0;
 47           }
 48       }
 49 }
 50 
 51 void isPrime(){
 52    LL i, j;
 53    isP[1]=1;
 54    for(i=2; i<M; ++i){
 55        if(!isP[i])  p[top++]=i;
 56        for(j=0; j<top && i*p[j]<M; ++j){
 57            isP[i*p[j]]=1;
 58            if(i%p[j]==0) break;
 59        }
 60    }
 61 }
 62 
 63 void solve(LL k){
 64    for(LL i=0; i<top && p[i]<=k; ++i){
 65        LL tmp=0;
 66        while(k%p[i]==0){
 67           ++tmp;
 68           k/=p[i];
 69        }
 70        
 71        if(tmp>cnt[i])
 72           cnt[i]=tmp;
 73    }
 74 }
 75 
 76 LL gcd(LL a, LL b){
 77    while(b){
 78       LL r=a%b;
 79       a=b;
 80       b=r;
 81    }
 82    return a;
 83 }
 84 
 85 int main(){
 86    LL n;
 87    isPrime();
 88    while(scanf("%lld", &n)!=EOF){
 89           memset(cnt, 0, sizeof(cnt));
 90           scanf("%lld", &q[0]); 
 91        for(LL i=1; i<n; ++i){
 92            scanf("%lld", &q[i]);
 93            LL tmp=q[0]-q[i]>0 ? q[0]-q[i] : q[i]-q[0];
 94            if(tmp!=0){
 95               LL GCD=gcd(tmp, q[0]*q[i]);
 96               solve(q[0]*q[i]/GCD);
 97               q[i]=tmp/GCD;
 98            }
 99            else q[i]=0;
100        } 
101        
102        LL ans2=0;
103        for(LL i=1; i<n; ++i)
104           ans2=gcd(ans2, q[i]);
105        if(cnt[0]>0)//除以2 
106            --cnt[0];
107        else ans2*=2; 
108      
109        bigN();
110        if(ans2==0){
111            endx=0;
112            ans[endx]=0;
113        }
114        printf("%lld", ans[endx]);
115        for(int i=endx-1; i>=0; --i)
116           printf("%04lld", ans[i]);
117        printf(" %lld\n", ans2);
118    }
119    return 0;
120 } 

 1 //用java爽一下,处理大数
 2 import java.util.Scanner;
 3 import java.util.Arrays;
 4 import java.math.*;
 5 import java.io.BufferedInputStream;
 6 class Main{
 7    static int[] tt = new int[1005];
 8    static int n;
 9    static int top=0;
10    static boolean[] flag = new boolean[10005];
11    static int[] p = new int[10005];
12    static int[] q = new int[10005];
13    static int[] aa = new int[10005];
14    public static void isprime(){
15        int i, j;
16        Arrays.fill(flag, false);
17        for(i=2; i<=10000; ++i){
18            if(!flag[i]) p[top++]=i;
19            for(j=0; j<top && i*p[j]<=10000; ++j){
20               flag[i*p[j]]=true;
21               if(i%p[j]==0) break;
22            }     
23        }
24        --top;
25        flag[1]=true;
26    }
27    public static void solve(int k){
28         int i, cnt;
29         for(i=0; i<=top && p[i]<=k; ++i){
30            cnt=0;
31            while(k%p[i]==0){
32                 ++cnt;
33                 k=k/p[i];
34              }
35            if(cnt>aa[i])
36               aa[i]=cnt;
37         }
38    }
39 
40    public static int gcd(int a, int b){
41        while(b!=0){
42           int r=a%b;
43           a=b;
44           b=r;
45        }
46        return a;
47    }
48    
49    
50    public static  void main(String[] args){
51        isprime();
52        Scanner input = new Scanner(new BufferedInputStream(System.in));
53        n=input.nextInt();
54        q[0]=input.nextInt();
55        for(int i=1; i<n; ++i){
56            q[i]=input.nextInt();
57            int temp=Math.abs(q[0]-q[i]);
58            if(temp!=0){
59               int GCD=gcd(temp, q[0]*q[i]);
60               solve(q[0]*q[i]/GCD);
61               q[i]=temp/GCD;
62            }
63            else q[i]=0;
64        }
65        
66        BigInteger bigN = BigInteger.ONE;
67        for(int i=0; i<=top; ++i){
68            for(int j=0; j<aa[i]; ++j)
69               bigN=bigN.multiply(BigInteger.valueOf(p[i]));
70        }
71        for(int i=0; i<=top; ++i)
72           if(aa[i]!=0)
73             System.out.println(p[i]+" "+aa[i]);
74        int ans=0;
75        for(int i=1; i<n; ++i){
76            ans=gcd(ans, q[i]);
77        }
78        if(aa[0]>0)
79             bigN=bigN.divide(BigInteger.valueOf(2));
80        else ans*=2;
81        if(ans==0)
82             bigN=BigInteger.ZERO;
83        System.out.println(bigN+" "+ans);
84    }
85 }

 



 

你可能感兴趣的:(poj)