P1029 [NOIP2001 普及组] 最大公约数和最小公倍数问题
一、穷举p和q
#include <bits/stdc++.h>
using namespace std;
//最大公约数
int gcd(int x, int y) {
return y ? gcd(y, x % y) : x;
}
//最小公倍数
int lcm(int x, int y) {
return y / gcd(x, y) * x; //注意顺序,防止乘法爆int
}
int cnt;
int x, y;
int main() {
//y的范围1e6,双重循环妥妥的TLE
cin >> x >> y;
//双重循环,傻查法,最基本,最朴素
for (int i = x; i <= y; i++)
for (int j = x; j <= y; j++)
if (gcd(i, j) == x && lcm(i, j) == y) cnt++;
cout << cnt << endl;
return 0;
}
此暴力算法,得分,有个点。看来需要优化一下。
二、利用p计算q
因为性质4知道:,所以已知最大公约和最小公倍,枚举,就可以通过上面的等式计算获得到,这比上面的枚举和的双重循环要减少一层循环,用信息学的行话就是时间复杂度由降为,历史级别的进步啊!!
#include <bits/stdc++.h>
using namespace std;
//最大公约数
int gcd(int x, int y) {
return y ? gcd(y, x % y) : x;
}
//最小公倍数
int lcm(int x, int y) {
return y / gcd(x, y) * x; //注意顺序,防止乘法爆int
}
int cnt;
int x; //最大公约数
int y; //最小公倍数
int main() {
//利用性质4:gcd(p,q)*lcm(p,q)=p*q
//可以减少一维循环
cin >> x >> y;
for (int p = x; p <= y; p++) { //穷举进化法
int q = x * y / p; //已知p,通过性质最大公约*最小公倍=两个数的乘积,
// 可以计算出另一个数字,这样,就可以去掉一层循环,效率明显提升。
// 应该满足如下的要求
if (gcd(p, q) == x && lcm(p, q) == y) cnt++;
}
cout << cnt << endl;
return 0;
}
到此,此题就已经了,可以说出题人还是比较良心,(≧▽≦)/ 但抓住一个好题,一定要一追到底,看看还能挖出哪些办法来。
三、穷举lcm(p,q)的约数
我们知道,和一定是最小公倍数的约数!(这不是废话吗?)如果我们能枚举的所有约数,就肯定能碰到!
那怎么才能枚举的所有约数呢?我们这里采用的是从遍历到的方法,试试,如果是的话,表示就是的约数。这样做,就可以找到中所有的小因子,对应的大因子除一下就是了。这两个其实是一对一对出现的,比如与就是两个。需要正着判断一次,反着再判断一次。同时小心类似于这样的情况,去重一个。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
/**
测试数据:
3 60
答案:4
*/
//最大公约数
LL gcd(LL x, LL y) {
return y ? gcd(y, x % y) : x;
}
//最小公倍数
int lcm(int x, int y) {
return y / gcd(x, y) * x; //注意顺序,防止乘法爆int
}
int cnt;
LL x; //最大公约数
LL y; //最小公倍数
int main() {
cin >> x >> y;
//理论依据:gcd(p,q)*lcm(p,q)=p*q
//枚举最小公倍数y的约数,这个约数可能是p,也可能是y/p
for (LL k = 1; k * k <= y; k++)
if (y % k == 0) {
//可能小因子是p,也可能大因子是p,但大小因子别一样,那样会算重了。
LL p = k;
LL q = x * y / k; //q是靠计算出来的。q=x*y/p
if (gcd(p, q) == x) cnt++;
//p=y/k,q=x*y/(y/k)=k*x 两组不能重复,就是 y/k!=k
if (k == y / k)continue;
//p是大因子的可能性
p = y / k;
q = k * x;
if (gcd(p, q) == x) cnt++;
}
cout << cnt << endl;
return 0;
}
这个计算效率就很牛了,时间复杂度:
四、穷举gcd(p,q)的倍数
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
/**
测试数据:
3 60
答案:4
*/
//最大公约数
LL gcd(LL x, LL y) {
return y ? gcd(y, x % y) : x;
}
//最小公倍数
int lcm(int x, int y) {
return y / gcd(x, y) * x; //注意顺序,防止乘法爆int
}
int cnt;
LL x; //最大公约数
LL y; //最小公倍数
int main() {
cin >> x >> y;
//理论依据:gcd(p,q)*lcm(p,q)=p*q
//枚举最大公约数x的倍数
for (LL p = x; p <= y; p += x) {
LL q = x * y / p;
if (gcd(p, q) == x && lcm(p, q) == y) cnt++;
}
cout << cnt << endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2018-08-28 ES优化总结
2017-08-28 使用 URLDecoder 和 URLEncoder 对统一认证中的http地址转义字符进行处理
2013-08-28 为DELL inspiron 14R安装CentOS X64 6.4