ロス最大公約数と谷P1029問題解決の最小公倍数

トピックリンク:https://www.luogu.com.cn/problem/P1029

タイトル説明

入力\(2 \)は正の整数\(X_0、Y_0(2 \ルX_0 \ 100000,2 LT \ルY_0 \ 1000000ル)\)以下の条件を満足するように求めて、\(P、Q \)数。
条件:

  1. \(P、Q \)は、正の整数です。
  2. 必要です(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は\) そしてこれが私たちの答えです。

おすすめ

転載: www.cnblogs.com/quanjun/p/11956484.html