专栏文章
题解:P1029 [NOIP 2001 普及组] 最大公约数和最小公倍数问题
P1029题解参与者 3已保存评论 5
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 5 条
- 当前快照
- 1 份
- 快照标识符
- @miq9rlh4
- 此快照首次捕获于
- 2025/12/04 01:16 3 个月前
- 此快照最后确认于
- 2025/12/04 01:16 3 个月前
题目大意
给定 ,求有序数对 使得 的数量。
思路
首先一看到这是一道有关于 和 (即最大公约数和最小公倍数)的问题,就简单地把欧几里得算法(即辗转相除(减)法)浅讲一下吧。
欧几里得算法
其实这就是一个很简单的港式大家记住就行:
那么我们把这个操作进行很多很多次,直到其中一个为 ,那么我们就得到这样一个形式 ,也就得出了 的值。
小结论
下面是一个再次体重要用到的结论:
随手证明一下吧。我们设:
这里, 为 的所有的不同质因数。
由于
代入到左式
得证。
接下来,我们正式开始做这道题。
首先,题目给出了 ,那么我们根据这个,就可以求出 的值,接下来,对于每一组 ,检验 是否等于 ,若成立,即可将其计入正确组数。
考虑优化。
由于对于每一组 满足题意(即 ,那么 也应当满足题意。所以我们只需枚举到 ,并检验 的正确性,假若正确,我们就能将这两组均计入可行方案。(建议不要直接讲循环的终止条件改为
i <= sqrt(n),而是 i * i <= n,这样精度会好些)再者,有一些数据会使得 ,那就没有上述交换的必要,所以只能加上一组。
代码
接下来就是代码咯
CPP#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll gcd(ll a, ll b) {return b == 0 ? a : gcd(b, a % b);}
ll lcm(ll a, ll b) {return a * b / gcd(a, b);}
int main() {
ll x, y, ans;
cin >> x >> y; x *= y;
for(ll i = 1; i * i <= x; i++) {
if(!(x % i)) {
ll a = i, b = x/i;
if(lcm(a, b) == y) {
if(a != b) ans++;
ans++;
}
}
}
cout << ans;
return 0;
}
相关推荐
评论
共 5 条评论,欢迎与作者交流。
正在加载评论...