首页 > 代码库 > 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 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。