poj 3101 大整数最小公倍数+欧几里得

来源:互联网 发布:阿里云服务器宽带价格 编辑:程序博客网 时间:2024/05/16 10:39

#include <iostream>#include <cstring>#include <cstdio>#include <math.h>#include <cstdlib>using namespace std;#define ll long long#define N 1000#define M 10000int t[N+5];int c[M+5];int res[M+5];int n;int prime[M],vis[M],cnt;int gcd(int a,int b){return b==0?a:gcd(b,a%b);}void cal(int s){for(int i=0;i<cnt && s>1;++i)if(s%prime[i]==0){int k=0;while(s%prime[i]==0){s/=prime[i];k++;}if(k>c[prime[i]])c[prime[i]]=k;}}void init(int n){int m=sqrt(n+0.5);cnt=0;for(int i=2;i<=m;++i)if(!vis[i]){for(int j=i*i;j<=n;j+=i)vis[j]=1;}for(int i=2;i<=n;++i)if(!vis[i])prime[cnt++]=i;}int main (){init(M);while(scanf("%d",&n)!=EOF){for(int i=1;i<=n;++i)scanf("%d",&t[i]);memset(c,0,sizeof(c));int nn=0;for(int i=2;i<=n;++i){int b=t[i]*t[1];int a=abs(t[i]-t[1])<<1;int d=gcd(a,b);a/=d; // 分数化简b/=d;nn=gcd(a,nn); // 分母部分不断求最大公约数cal(b);}memset(res,0,sizeof(res));res[1]=1;// 压4位的高精度大整数乘法for(int i=1;i<=M;++i)for(int j=1;j<=c[i];++j){int temp=0;for(int k=1;k<=N;++k){res[k]=res[k]*i+temp;temp=res[k]/M;res[k]%=M;}}int index=N;for( ; res[index]==0 ;--index) ;printf("%d",res[index--]);for(;index>=1;--index)printf("%04d",res[index]);printf(" %d\n",nn);}return 0;}

1. 每两个星球 i , j 的时间间隔为 0.5L/abs(1/ti - 1/tj) ,化简: ti * tj /  2*abs(ti - tj) ,即我们只要满足每两个的表达式为整数就可以

2.其他的每个星球都与第一个星球的时间间隔为整数,他们的时间间隔也为整数,所以就不用枚举 n*n 次 , O(n) 就好

3. 令 b=ti*tj , a=2*abs(ti-tj) ,满足每个 b/a 都为整数 ,注意 b和a 可能不是最简分数,要化简, ans 的分子部分是所有 b 的最小公倍数 ,ans 的分母是所有a的最大公约数



原创粉丝点击