Common Divisors

Common Divisors
Codeforces medium

يُعطى لك مصفوفة \(a\) من \(n\) أعداد صحيحة. أوجد عدد الأعداد الصحيحة الموجبة \(x\) التي تقسم كل عناصر المصفوفة.

القيود:

  • \(1 \le n \le 4 \cdot 10^5\)
  • \(1 \le a_i \le 10^{12}\)

الإدخال:

  • السطر الأول: عدد صحيح \(n\).
  • السطر الثاني: \(n\) عددًا \(a_1, a_2, \dots, a_n\).

المخرجات:

  • عدد صحيح واحد — عدد القواسم المشتركة لكل العناصر.

مثال:

الإدخال:

6
6 90 12 18 30 18

المخرجات:

4

(القواسم المشتركة هي \(1\) و \(2\) و \(3\) و \(6\).)

الحل

يقسم العدد كل عناصر المصفوفة تمامًا عندما يقسم القاسم المشترك الأكبر لها. لذلك الجواب هو عدد قواسم

\[ g = \gcd(a_1, a_2, \dots, a_n). \]

نحسب \(g\) خطوة بعد خطوة: \(\gcd(a_1, a_2, a_3) = \gcd(\gcd(a_1, a_2), a_3)\)، وهكذا. نبدأ بالقيمة \(g = 0\)، لأن \(\gcd(0, x) = x\).

ثم نعدّ قواسم \(g\) بطريقة \(O(\sqrt{g})\) من درس القواسم: كل قاسم \(i \le \sqrt{g}\) يأتي مع شريكه \(g / i\)، ونعدّ الشريك فقط إذا كان مختلفًا عن \(i\).

بما أن \(g \le 10^{12}\)، فإن الحلقة تُجري \(10^6\) خطوة على الأكثر. تصل القيم إلى \(10^{12}\)، لذلك نستخدم long long، وكذلك في الدالة gcd.

#include <iostream>
using namespace std;

long long gcd(long long a, long long b) {
    if (b == 0) return a;
    return gcd(b, a % b);
}

int main() {
    int n;
    cin >> n;

    long long g = 0;  // gcd(0, x) = x
    for (int i = 0; i < n; i++) {
        long long a;
        cin >> a;
        g = gcd(g, a);
    }

    // count the divisors of g
    int divisors = 0;
    for (long long i = 1; i * i <= g; i++) {
        if (g % i == 0) {
            divisors++;           // the small divisor i
            if (i != g / i) {
                divisors++;       // its partner g / i
            }
        }
    }

    cout << divisors << "\n";
}