首页 > 代码库 > poj 3101Astronomy(圆周追击+分数最小公倍数)

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 }