poj 3101 Astronomy (GCD LCM 高精度)
2012-07-30 11:38
381 查看
题目链接:http://poj.org/problem?id=3101
大致题意:一个恒星系统中有n(2 ≤ n ≤ 1 000)颗行星,告诉你它们的运转周期Ti(1 ≤ ti ≤ 10 000),求他们能够同线的最小周期,表示形式是:分子 分母
样例:
Sample Input
Sample Output
思路:仔细看图就知道任意两颗行星共线,则 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)的时候先对分子和分母进行约分,这样就能够保证最后分子分母互质。
大致题意:一个恒星系统中有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)的时候先对分子和分母进行约分,这样就能够保证最后分子分母互质。
#include<cstdio> #include<cstring> #include<cmath> int prime[5000],head,Div[5000]; bool isprime[10005]; void getPrime(){ head=0; memset(isprime,0,sizeof(isprime)); for(int i=2;i<10000;i++)if(!isprime[i]){ prime[head++]=i; for(int j=2*i;j<10000;j+=i){ isprime[j]=true; } } } int gcd(int a,int b){ if(b==0){ return a; } return gcd(b,a%b); } int lcm(int a,int b){ return a*b/gcd(a,b); } const int MAXNUM=1005; int d[MAXNUM],den[MAXNUM]; int main(){ int n,i,j,k,f,numerator; getPrime(); while(~scanf("%d",&n)){ numerator=0; memset(Div,0,sizeof(Div)); memset(den,0,sizeof(den)); den[0]=1; for(i=0;i<n;i++){ scanf("%d",&d[i]); } for(i=1;i<n;i++){ if(d[i]==d[0])continue; int LCM=lcm(d[i],d[0]); //求分母 f=2*(int)fabs(LCM/d[i]-LCM/d[0]); //求分子 int temp=gcd(LCM,f); LCM/=temp; //分子分母约分 f/=temp; numerator=gcd(numerator,f); //求最大公约数 for(j=0;j<head;j++){ //分解质因数 int t=0; while(LCM%prime[j]==0){ t++;LCM/=prime[j]; } if(Div[j]<t)Div[j]=t; //记录较大的指数 if(LCM==1)break; } } for(i=0;i<head;i++){ for(j=0;j<Div[i];j++){ int temp=0; for(k=0;k<MAXNUM;k++){ //大数表示 den[k]=den[k]*prime[i]+temp; temp=den[k]/10000; den[k]%=10000; } } } for(i=MAXNUM-1;i>=0;i--)if(den[i]!=0)break; printf("%d",den[i]); while(i>0)printf("%04d",den[--i]); //由于表示的4位数可能有前头0,所以强制输出4位 printf(" %d\n",numerator); } return 0; }
相关文章推荐
- POJ3101 Astronomy——高精度+分解质因子法求GCD和LCM——Pku3101
- poj 3101 Astronomy (java 分数的最小公倍数 gcd)
- POj-3101-Astronomy(分数GCD+BigInteger)
- POJ 3101 Astronomy (大数+LCM)
- poj3101——Astronomy(大数数学&gcd)
- POJ 3101 Astronomy (挖坑待学Java……最小公倍数---大数表示)
- POJ 2429 GCD & LCM Inverse (整数分解,由gcd+lcm求a,b)
- POJ, 2429 GCD & LCM Inverse
- POJ 2429 - GCD & LCM Inverse(数论)
- POJ 3101 Astronomy 可能会
- poj 3101 Astronomy (大数java)
- POJ 2429 GCD & LCM Inverse ★(pollard-ρ && DFS枚举)
- POJ 3101 Astronomy
- POJ 2429 GCD & LCM Inverse (Pollard rho整数分解+dfs枚举)
- POJ 3101 大数+gcd
- poj2429 GCD & LCM Inverse 因数分解pollard_rho算法
- POJ 3101 Astronomy (角速度啊,高中物理啊。。。T_T)
- poj 2429 GCD & LCM Inverse
- POJ 2429 GCD & LCM Inverse(大整数素因子分解+二进制枚举)
- POJ 2429 GCD & LCM Inverse ★(pollard-ρ && DFS枚举)