POJ3101 Astronomy——高精度+分解质因子法求GCD和LCM——Pku3101

经典的求分数GCD和LCM的题目。方法:分别求出每个行星对于第一颗行星的相对速度,设其为ai/bi,那么答案就是乘上的一个最小的分数使得所有ai/bi与它相乘之后都为整数。那么这个分数就是:

(所有bi的LCM)

--------------

(所有ai的GCD)

用分解质因子的方法就可以求出这个分数了。注意要用高精度。

代码如下:

Program Astronomy;//By_Thispoet

Const

	maxn=10000;

Type

	arr=array[0..maxn]of Longint;

Var

	i,j,k,m,n,tmp				:Longint;

	t,fz,fm						:Array[0..maxn]of Longint;

	map,num						:Array[0..maxn]of Longint;

	prime						:Array[1..maxn*10]of Boolean;

	ans							:arr;

	flag						:Boolean;





Function Max(i,j:Longint):Longint;

begin

	if i>j then exit(i);exit(j);

end;





Function Min(i,j:Longint):Longint;

begin

	if i<j then exit(i);exit(j);

end;





Function Gcd(i,j:Longint):Longint;

begin

	if j=0 then exit(i);

	exit(Gcd(j,i mod j));

end;





Procedure Printf(i:Longint);

begin

	if i>=1000 then write(i) else

		if i>=100 then

			begin

				write(0);

				write(i);

			end else if i>=10 then

				begin

					write('00');

					write(i);

				end else

					begin

						write('000');

						write(i);

					end;

end;





Procedure Multiply(i:Longint;var p:arr);

var j,k:Longint;

begin



	for j:=1 to p[0] do

		p[j]:=p[j]*i;

	j:=1;

	while j<=p[0] do

		begin

			inc(p[j+1],p[j] div 10000);

			p[j]:=p[j] mod 10000;

			if p[p[0]+1]>0 then inc(p[0]);

			inc(j);

		end;



end;





Procedure Prime_Prepare;

begin

	prime[1]:=false;

	for i:=2 to maxn do

		if prime[i] then

			begin

				inc(map[0]);

				map[map[0]]:=i;

				j:=i<<1;

				while j<=maxn do

					begin

						prime[j]:=false;

						inc(j,i);

					end;

			end;

end;





BEGIN



	readln(n);

	fillchar(prime,sizeof(prime),1);

	Prime_Prepare;

	while not eof do

		begin

			flag:=false;



			t[0]:=0;

			for i:=1 to n do read(t[i]);



			for i:=2 to n do

				begin

					fz[i]:=t[i-1]*t[i];

					fm[i]:=abs(t[i-1]-t[i]);

					if fm[i]<>0 then

						begin

							tmp:=Gcd(fz[i],fm[i]);

							fz[i]:=fz[i] div tmp;

							fm[i]:=fm[i] div tmp;

						end;

				end;



			fillchar(num,sizeof(num),0);

			ans[0]:=1;ans[1]:=1;



			for i:=2 to n do

				begin

					if fm[i]<>0 then

						begin

							for j:=1 to map[0] do

								if fz[i]<map[j] then break else

									begin

										if fz[i] mod map[j]=0 then

											begin

												tmp:=0;

												while fz[i] mod map[j]=0 do

													begin

														inc(tmp);

														fz[i]:=fz[i] div map[j];

													end;

												num[j]:=Max(num[j],tmp);

											end;

									end;

						end;

				end;



			for i:=1 to map[0] do

					if num[i]>0 then

						begin

							if (not flag)and(not odd(map[i])) then

								begin

									dec(num[i]);

									flag:=true;

								end;

							for j:=1 to num[i] do

								Multiply(map[i],ans);

						end;



			fillchar(num,sizeof(num),127);



			write(ans[ans[0]]);

			for i:=ans[0]-1 downto 1 do

				printf(ans[i]);



			write(' ');



			fillchar(ans,sizeof(ans),0);

			ans[0]:=1;ans[1]:=1;

			for i:=2 to n do

				begin

					if fm[i]<>0 then

						begin

							for j:=1 to map[0] do

									begin

										tmp:=0;

										if fm[i] mod map[j]=0 then

											begin

												while fm[i] mod map[j]=0 do

													begin

														inc(tmp);

														if tmp>=num[j] then break;

														fm[i]:=fm[i] div map[j];

													end;

											end;

										num[j]:=Min(num[j],tmp);

									end;

						end;

				end;

		

			for i:=1 to map[0] do

					if num[i]<maxint then

						begin

							for j:=1 to num[i] do

								Multiply(map[i],ans);

						end;	

			if not flag then Multiply(2,ans);

	

			write(ans[ans[0]]);

			for i:=ans[0]-1 downto 1 do

				printf(ans[i]);		

	

			writeln;

			readln(n);

			if n=0 then break;

		end;

	

END.



你可能感兴趣的:(poj)