回 帖 发 新 帖 刷新版面

主题:一个关于最大公约数和最小公倍数的问题

最近本小虾在做题时遇到这样一道:

[color=FF0000]NOI’2001第七届全国青少年信息学(计算机)奥林匹克分区联赛

复赛试题  普及组

题二 最大公约数和最小公倍数问题(20分)

问题描述

输入二个正整数x0,y0(2<=x0<100000,2<=y0<=1000000),求出满足下列条件的P,Q的个数

条件:  1.P,A是正整数

2.要求P,Q以x0为最大公约数,以y0为最小公倍数.

试求:满足条件的所有可能的两个正整数的个数.

样例

输入:x0=3   yo=60

输出:4

说明(不用输出)此时的  P  Q  分别为:

    3   60

15      12

12      15

60       3

所以:满足条件的所有可能的两个正整数的个数共4种.[/color]

我是这样算的:

program noip2;

var
n,i,k:longint;
x,y,t:longint;

function fj(n:integer):integer;
var
i,t:integer;
begin
t:=0;
for i:=2 to n do
begin
if n mod i=0 then
begin
t:=t+1;
n:=trunc(n/i);
end
else break;
end;
fj:=t;
end;                      {将一个数因式分解,求它的质因数个数(重复的不算)}

function jc(t:integer):longint;
var
i:integer;
s:longint;
begin
s:=1;
for i:=1 to t do
s:=s*i;
jc:=s;
end;                      {定义阶乘n!=1*2*3*...*n}

function zh(n,m:integer):integer;
var a,b,c:longint;
begin
a:=jc(n);
b:=jc(m);
c:=jc(n-m);
zh:=trunc(a/(b*c));
end;                      {定义组合数函数=n!/[m!*(n-m)!]}

begin
readln(x,y);
t:=fj(y)-fj(x);
n:=0;
for i:=0 to t do
n:=n+zh(t,i);
writeln(n);
end.

请各位大虾帮我优化一下,或者有什么更简单更好的算法,请写出来,谢谢!

回复列表 (共6个回复)

沙发

一个简单但可能超时或大数据不能通过的做法:
var
  略……
function f(x,y:longint):longint;{求x、y的最大公约数}
begin
  if x=0 then f:=y
  else f:=f(y mod x,x);
end;
begin
t1:=x0*y0;
t2:=trunc(sqrt(t1));
total:=0;
for i:=x0 to t2 do
begin
  j:=t1 div i;
  if i*j=t1
  then if f(i,j)=x0
       then inc(total);
end;
writeln(total);
end.

板凳

我有个更好的方法

function f(x,y:longint):longint;
begin
  if x=0 then f:=y
  else f:=f(y mod x,x);
end;

var
略.
begin
t:=y0 div x0;
total:=0;
for i:=1 to trunc(sqrt(t)) do
  if(t mod i=0)and(f(i,t div i)=1) then
   inc(total):
writeln(total);
end.

3 楼

两位算法都不错
林记的稍好
美中不足:应该把结果乘以2
谢谢两位的指点

4 楼

NONO,用辗转相除法(估计这个很陌生,我也是),加入是M,N两个数字,用M 向N求余数,然后将N变M,余数变N,然后反复计算,直到余数=0,这个方法相对比那些简单,但是原理十分复杂,我是听以前一个教授讲的

5 楼

[em54]我们不是用的辗相除法吗,这只不过是用来求最大公约数的,
用的着这么神秘么?

6 楼

我有个方法,有错的请高手门指点一下
var
x,y,total:integer;
procedure t(a,b:integer);
var x1,x2,q:integer;
begin
  while a<=y do
  begin
    while b<=y do
    begin
      x1:=a;x2:=b;
      repeat
        q:=x1 mod x2;
        x1:=x2;
        x2:=q;
      until x2=0;
    if x1=x then
      if a*b/x1=y then inc(total);
    b:=b+3;
    end;
    a:=a+3;
    b:=3;
  end;
end;
begin
readln(x,y);
t(x,x);
write(total);
end.

我来回复

您尚未登录,请登录后再回复。点此登录或注册