トピックリンク:https://www.luogu.com.cn/problem/P1029
タイトル説明
入力\(2 \)は正の整数\(X_0、Y_0(2 \ルX_0 \ 100000,2 LT \ルY_0 \ 1000000ル)\)以下の条件を満足するように求めて、\(P、Q \)数。
条件:
- \(P、Q \)は、正の整数です。
- 必要です(P、Q \)\に(X_0 \)\に最大公約数される(Y_0 \)は\最小公倍数です。
テスト要件:すべての可能の条件を満たす\(2 \)正の整数です。
入力形式
\(2 \)正の整数\(X_0、Y_0 \)
出力フォーマット
\(1 \)取得の条件を示す番号\(P、Q \)番号
分析
この質問、名前「最大公約数と最小公倍数の問題」と、それは確かに最大公約数とソリューションの最小公倍数で行うことができますが、質問は本発明の方法はまた、品質係数の分解を解決するために使用することができるであるが。
ここでは、この問題を解決するには2つの方法があります。
ソリューション1 GCD +列挙
GCDは、実際には「最大公約数」(最大公約数)速記です。
まず、それは私たちに2つの数値を与えます\(X_0 \)と\(Y_0 \)場合、(X_0 \)\で割り切れることはできません(Y_0 \)\、そして、答えは間違いなく\(0 \)ヶ月。
そうでなければ、我々はから持っている\(X_0 \)に\(Y_0 \)列挙するために、すべての道\(P \)によると、(P \)\我々が得ることができます\(Q \)です\(X_0 \回Y_0 / P \) 。
もちろん、この場合には、\(Q \) 、必ずしも有効ではありません
\(Q \)場合のみ有効\(GCD(P、Q)= X_0 \) 。
ときに統計を見て\(P \)間隔で\([X0、Y0]が\ ) 正当な数の範囲を持っている\(Qは\)することができます。
次のようにコードは次のとおりです。
#include <bits/stdc++.h>
using namespace std;
long long x, y;
long long gcd(long long a, long long b) {
if (b == 0) return a;
return gcd(b, a%b);
}
int main() {
cin >> x >> y;
if (y % x) puts("0");
else {
int cnt = 0;
for (long long p = x; p <= y; p ++) {
if (y % p || p % x) continue; // P必须满足能被x0整除,同时能整除y0
long long q = x * y / p;
if (gcd(p, q) == x) cnt ++;
}
cout << cnt << endl;
}
return 0;
}
この質問は、しかし、より高速なソリューションがあり、これは私がご紹介するつもりです。
方法2素因数分解
私たちの「分解品質係数の」この問題を解決するためのアプローチ。
場合はまず、\(x0が\)で割り切れることはできません\(Y0 \) 、そして、答えは肯定的である\(0 \) 、ダイレクト出力\(0 \)することができます。
第二には、私たちが作る(= N-Y_0 / X_0 \)\そして、(N- \)\素因数分解のために、それが想定され、\(N- \)表現の素因数分解のためである:
\(^ {N-A_1 = B_1 } \回A_2 ^ {B_2}
\回\ドット\回A_M ^ {b_m} \) 、その後、我々はのいずれかのために、それを知っている\(a_iを\)、それはどちらかに戻ります)\(\ Pを、またはに行く\ (Q \) 、何もないことができます\(1 \)\(a_iを\)への復帰\(P \) 、および他の\(a_iを\)への復帰(Q \)\彼らは今回最大のコンベンションであるため、(数になり(X0 \タイムズa_iを\)\ので、このために)、\(M \)\(a_iを\) 、または、彼らは反対している)\ P(\、またはにプロパティ\(Q \)したがって、プログラムの総数は(2 ^ M \)\。
次のようにコードは、(使用されるコードのIです\(CNT \)異なる品質係数の数を示すために):
#include <bits/stdc++.h>
using namespace std;
int x, y, n, m;
int main() {
cin >> x >> y;
if (y % x) puts("0");
else {
n = y / x;
int a = sqrt(n); // 求平方根
for (int i = 2; i <= a; i ++) {
if (n % i == 0) {
m ++;
while (n % i == 0) n /= i;
}
}
if (n > 1) m ++;
cout << (1<<m) << endl;
}
return 0;
}
学んビットコンピューティングの学生がコードすることを認識する必要があります\(1 << mは\)実際に表し\(2 ^ mは\) 、そしてこれが私たちの答えです。