zoukankan      html  css  js  c++  java
  • poj 3101 Astronomy (GCD LCM 高精度)

    题目链接:http://poj.org/problem?id=3101

    大致题意:一个恒星系统中有n(2 ≤ n ≤ 1 000)颗行星,告诉你它们的运转周期Ti(1 ≤ ti ≤ 10 000),求他们能够同线的最小周期,表示形式是:分子 分母

    Time Limit: 2000MS   Memory Limit: 65536K

    样例:

    Sample Input

    3
    6 2 3

    Sample Output

    3 1

                                   

    思路:仔细看图就知道任意两颗行星共线,则 x/t1 - x/t2 = 0 mod (1/2),运行距离差为半个周长的整数倍即可,整理得到(t2-t1)*x/(t1*t2) = 0 mod (1/2),这样的方程可以列n*(n-1)/2个。但不需要这么多,我们都以第一颗行星作为标尺 x/t1 - x/t2 = 0 mod(1/2) ,x/t1 - x/t3 = 0 mod(1/2),两式相减得到 x/t3 - x/t2 = 0 mod(1/2)

    所以只需要这n-1个公式成立即可。再将上述式子变形:x*(2/t1-2/t2)=0 mod 1,那么问题就转化为求(2/t1-2/ti) (2 ≤ i ≤ n)中分母的最小公倍数和分子的最大公约数,最小公倍数的答案的分子,最大公约数是答案的分母。想不通的找几个分数通分一下就懂了。

    一开始用的是简单求lcm,提交WA了。回头看看数据范围,1 ≤ ti ≤ 10 000,考虑极限情况,如果把10000以内的质数大小都看作是10^4 那么1000个数的乘积就是10^4000次方。这样计算,这个题求LCM还需要高精度,求的最大公约数就不用了,最大公约数明显小与10000。1.可以用JAVA大数直接算。 2.LCM(a,b)=∏ (pi^max(ai,bi)),把a,b 质因数分解 分别表示成∏ (pi^ai)和∏ (pi^bi)的形式,如果a或b中一个有质因子p一个没有,则没有质因子p的指数设成0,这样就能保证表示的一致性。这样就能把最小公倍数以质因数分解的形式表示了。还原成大数可以用一个数组表示,数组中每个数占4-5位。

    这里有一个细节要注意,由于最大公倍数是由数组表示的,在分子和分母约分的时候会很困难,所以我们求(2/t1-2/ti)的时候先对分子和分母进行约分,这样就能够保证最后分子分母互质。

     

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cmath>
     4 int prime[5000],head,Div[5000];
     5 bool isprime[10005];
     6 void getPrime(){
     7     head=0;
     8     memset(isprime,0,sizeof(isprime));
     9     for(int i=2;i<10000;i++)if(!isprime[i]){
    10         prime[head++]=i;
    11         for(int j=2*i;j<10000;j+=i){
    12             isprime[j]=true;
    13         }
    14     }
    15 }
    16 int gcd(int a,int b){
    17     if(b==0){
    18         return a;
    19     }
    20     return gcd(b,a%b);
    21 }
    22 int lcm(int a,int b){
    23     return a*b/gcd(a,b);
    24 }
    25 const int MAXNUM=1005;
    26 int d[MAXNUM],den[MAXNUM];
    27 int main(){
    28     int n,i,j,k,f,numerator;
    29     getPrime();
    30     while(~scanf("%d",&n)){
    31         numerator=0;
    32         memset(Div,0,sizeof(Div));
    33         memset(den,0,sizeof(den));
    34         den[0]=1;
    35         for(i=0;i<n;i++){
    36             scanf("%d",&d[i]);
    37         }
    38         for(i=1;i<n;i++){
    39                 if(d[i]==d[0])continue;
    40                 int LCM=lcm(d[i],d[0]);  //求分母
    41                 f=2*(int)fabs(LCM/d[i]-LCM/d[0]);  //求分子
    42                 int temp=gcd(LCM,f);
    43                 LCM/=temp;  //分子分母约分
    44                 f/=temp;
    45                 numerator=gcd(numerator,f);  //求最大公约数
    46                 for(j=0;j<head;j++){  //分解质因数
    47                     int t=0;
    48                     while(LCM%prime[j]==0){
    49                         t++;LCM/=prime[j];
    50                     }
    51                     if(Div[j]<t)Div[j]=t;  //记录较大的指数
    52                     if(LCM==1)break;
    53                 }
    54         }
    55         for(i=0;i<head;i++){
    56             for(j=0;j<Div[i];j++){
    57                 int temp=0;
    58                 for(k=0;k<MAXNUM;k++){  //大数表示
    59                     den[k]=den[k]*prime[i]+temp; 
    60                     temp=den[k]/10000;
    61                     den[k]%=10000;
    62                     
    63                 }
    64             }
    65         }
    66         for(i=MAXNUM-1;i>=0;i--)if(den[i]!=0)break;
    67         printf("%d",den[i]);
    68         while(i>0)printf("%04d",den[--i]);  //由于表示的4位数可能有前头0,所以强制输出4位
    69         printf(" %d\n",numerator);
    70     }
    71     return 0;
    72 }

     

  • 相关阅读:
    redis 专题 (一)总纲和命令
    CentOS 7安装 .net core 环境
    IdentityServer4 学习笔记(一)客户端模式
    IdentityServer4 学习笔记(开篇)
    ASP.NET Core 自定义视图路径及主题切换
    ASP.NET 国密加密 SM2-SM4
    ASP.NET Framework 如何利用nuget打包,并发布到nuget平台
    ASP.NET Core 在windows服务器安装dotnet-hosting-2.2.6-win 时出现应用程序池停止问题的解决方案
    三分钟学会Redis在.NET Core中做缓存中间件
    ASP.NET CORE 2.2 因外键设置的双向导航对象序列化报 循环错误问题的解决
  • 原文地址:https://www.cnblogs.com/mcflurry/p/2614991.html
Copyright © 2011-2022 走看看