题解 P1029 【最大公约数和最小公倍数问题】

千年知乎_天才

2019-09-18 11:06:07

Solution

题目名称:最大公约数和最小公倍数问题 来源:2001年NOIP普及组 # 链接 ## 博客链接 - [博客园](https://www.cnblogs.com/Alvin-Tree/p/11563042.html) - [CSDN](https://blog.csdn.net/weixin_43890363/article/details/100937310) - [洛谷博客](https://www.luogu.org/blog/131abc155-7341-6424/solution-p1029) - [洛谷题解](https://www.luogu.org/problemnew/solution/P1029) ## 题目链接 - [Vijos](https://vijos.org/p/1131) - [洛谷(P1029)](https://www.luogu.org/problem/P1029) - [入门OJ(1172)](https://begin.lydsy.com/JudgeOnline/problem.php?id=1172) # 题解 约定$D=min(x_0,y_0),M=max(x_0,y_0)$ `情况1:` $M \mod D\neq0$ 显然,无解。 `情况2:` $M \mod D=0$ 推一波 $$ \because (P,Q)=D,[P,Q]=M $$ $$ \therefore P\times Q=(P,Q)[P,Q]=D\times M $$ $$ p=P\div D,q=Q\div D,prod=D\div M $$ $$ \therefore p\times q=prod\&(p,q)=1 $$ 当然,暴力枚举$p$就可以通过此题,时间复杂度$O(\sqrt{prod}\times \log(\sqrt{prod}))$。 但是这次笔者要将一个更优的解法。 由推出来的式子可得,我们就要求有多少对$prod$的因数互质。 现将$prod$分解质因子得到$prod$有$n$种质因子。 对于质因子$d$,要么只是$p$的质因子,要么只是$q$的质因子(如果$p$和$q$同时拥有这个质因子$d$,那么$(p,q)\neq 1$),并且$d$至少要是其中一个的因数(否则$p\times q\neq prod$)。 所以说其中每种质因子都有两种可能,则答案是$2^n$。 时间复杂度$O(玄学)$,(最坏$O(\sqrt{prod})$,最好$O(\log(prod))$) ```cpp //C++ #include<bits/locale_facets.h> #include<stdio.h> #define forto(name,i,d,u) for(name i=d;i<=u;i++) inline void output(long long o); inline long long input(); int main() { short numeral=0; int x=input(),y=input(); if(y%x)return putchar('0'),0; y/=x; forto(int,i,2,y/i) if(!(y%i)) { numeral++; while(!(y%i))y/=i; } if(y>1)numeral++; output(1<<numeral); return 0; } inline void output(long long o) { if(o<0)putchar('-'),o=-o; if(o>=10)output(o/10); putchar(o%10^'0'); } inline long long input() { bool minus=false; char now=getchar(); long long i=0; for(;!isdigit(now);now=getchar()) if(now=='-')minus=!minus; for(;isdigit(now);now=getchar())i=(i<<3)+(i<<1)+(now^'0'); return minus?-i:i; } ``` ```pascal //pascal var numeral:1..30; x:2..100000; i,y:1..1000000; begin readln(x,y); if y mod x>0 then begin write('0'); halt; end; y:=y div x; i:=2; while i<=y div i do begin if y mod i=0 then begin inc(numeral); while y mod i=0 do y:=y div i; end; inc(i); end; if y>1 then inc(numeral); write(1 shl numeral); end. ```