题目大意:
求n1个a[i]的乘积跟n2个b[i]乘积的既约分数,(既约分数就是分子分母最大公约数为1的分数)。
对于20%的数据,n1,n2<=10,Ai,Bi<=10
对于60%的数据,n1,n2<=1000,Ai,Bi<=1000
对于100%的数据,n1,n2<=100000,Ai,Bi<=10000
数据保证不会出现分数的值为0的情况
题解:
20分的就是直接得到乘积后直接用辗转相除法约去最大公因数即可
时间复杂度:O(n)
60分就使用高精度,把两个序列两两去除公因数
AC的话:
因为Ai,Bi<=10000,所以可以先塞素数,然后对其分解质因数,把合数化成质数(质数则不变),然后2个序列a,b都这样做,最后用两个序列的分解出来的数相互抵消,类似于去重。
然后将2个序列剩下的数分别用高精度算出乘积,然后直接输出
PS:抵消完后的序列乘积满足既约分数。
不过我们在高精度的时候要用到压位,不然容易超时,即改变进制,因为Ai,Bi<=10000,所以长整型最大压位到200000左右…
时间复杂度O(n*m)
M为常数,不会超过100,因为10000以内我们只需分解到100即可,分解完后如果还大于1,则可证这一定是个质数
var
a,b,ansa,rp:array [0..100001] of longint;
p:array [0..10001] of boolean;
kp:array [0..10001] of longint;
x,i,j,k,l,n,m,la:longint;
procedure gjd(k:longint);
var
j,x:longint;
begin
x:=0;
for j:=1 to la do
begin
ansa[j]:=k*ansa[j]+x;
x:=ansa[j] div 100000;
ansa[j]:=ansa[j] mod 100000;
end;
ansa[la+1]:=x;
la:=la+1;
if ansa[la]=0 then dec(la);
end;
function check(p:longint):string;
begin
check:='';
if p<=9999 then check:=check+'0';
if p<=999 then check:=check+'0';
if p<=99 then check:=check+'0';
if p<=9 then check:=check+'0';
exit(check);
end;
procedure ag(k:longint);
begin
inc(a[kp[k]]);
if k=kp[k] then exit;
ag(k div kp[k]);
end;
procedure bg(k:longint);
begin
inc(b[kp[k]]);
if k=kp[k] then exit;
bg(k div kp[k]);
end;
begin
assign(input,'count.in'); reset(input);
assign(output,'count.out'); rewrite(output);
read(n);
for i:=1 to n do
begin
read(x);
inc(a[x]);
end;
readln;
read(m);
for i:=1 to m do
begin
read(x);
inc(b[x]);
end;
readln;
p[1]:=true;
kp[1]:=1;
for i:=2 to 10000 do
if not(p[i]) then
begin
j:=1;
while i*j<=10000 do
begin
p[i*j]:=true;
if kp[i*j]=0
then kp[i*j]:=i;
inc(j);
end;
end;
for i:=2 to 10000 do
begin
k:=a[i]; a[i]:=0;
for j:=1 to k do ag(i);
k:=b[i]; b[i]:=0;
for j:=1 to k do bg(i);
end;
for i:=2 to 10000 do
begin
if a[i]>=b[i]
then begin
a[i]:=a[i]-b[i];
b[i]:=0;
end
else begin
b[i]:=b[i]-a[i];
a[i]:=0;
end;
end;
ansa[1]:=1;
la:=1;
for i:=2 to 10000 do
for j:=1 to a[i] do gjd(i);
write(ansa[la]);
ansa[la]:=0;
for i:=la-1 downto 1 do
begin
write(check(ansa[i]));
write(ansa[i]);
ansa[i]:=0;
end;
la:=1;
ansa[1]:=1;
for i:=2 to 10000 do
for j:=1 to b[i] do gjd(i);
write(' ');
if (ansa[1]=1) and (la=1)
then begin end
else begin
write(ansa[la]);
for i:=la-1 downto 1 do
begin
write(check(ansa[i]));
write(ansa[i]);
end;
end;
close(input); close(output);
end.