[jzoj]2538.【NOIP2009TG】Hankson 的趣味题
Link
https://jzoj.net/senior/#main/show/2538
Description
Hanks 博士是BT (Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫Hankson。现在,刚刚放学回家的Hankson 正在思考一个有趣的问题。今天在课堂上,老师讲解了如何求两个正整数c1 和c2 的最大公约数和最小公倍数。现在Hankson 认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数a0,a1,b0,b1,设某未知正整数x 满足
1、x 和a0 的最大公约数是a1;
2、x 和b0 的最小公倍数是b1。
Hankson 的“逆问题”就是求出满足条件的正整数x。但稍加思索之后,他发现这样的x 并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的x 的个数。请你帮助他编程求解这个问题。
Solution
50分
显然,答案肯定是最大公约数的倍数,枚举那个数即可。
100分
如果存在两个数,a,b,分解质因数得
a=p1q1*p2q2*p3q3......
b=pp1qq1*pp2qq2*pp3qq3......
那么,最大公约数和最小公倍数分别如下。
gcd(a,b)=p1min(q1,qq1)p2min(q2,qq2)p3min(q3,qq3)......
lcm(a,b)=p1max(q1,qq1)p2max(q2,qq2)p3max(q3,qq3)......
我们根据这个关系,将题目所给的lcm,也就是b1分解质因数,根据第二条,我们枚举他每个质因数的指数,判断答案即可。
注意卡常。
Code
{$inline on} var n,x,i,j,g,a0,a1,b0,b1,now,ans:longint; sm:array[1..10,1..2] of longint; function gcd(x,y:longint):longint; inline; begin if x mod y=0 then exit(y); exit(gcd(y,x mod y)); end; procedure dg(k:longint;ka:int64); var i:longint; begin if k>g then begin if (gcd(ka,a0)=a1) and (ka div gcd(ka,b0)*b0=b1) then inc(ans); exit; end; for i:=0 to sm[k,2] do begin dg(k+1,ka); ka:=ka*sm[k,1]; end; end; begin readln(n); for i:=1 to n do begin readln(a0,a1,b0,b1); x:=b1; g:=0; fillchar(sm,sizeof(sm),0); for j:=2 to trunc(sqrt(b1)) do begin if x mod j=0 then begin inc(g); sm[g,1]:=j; while x mod j=0 do begin x:=x div j; inc(sm[g,2]); end; if x=1 then break; end; end; if x>1 then begin inc(g); sm[g,1]:=x; sm[g,2]:=1; end; ans:=0; dg(1,1); writeln(ans); end; end.