Tam kvadratla cütlər#12428

Tam kvadratla cütlər (Həll təhlili)

İstənilən natural ədəd yeganə şəkildə i = k \cdot x^2 kimi göstərilə bilər, burada kvadratsızdır, yəni heç bir sadə ədədin kvadratına bölünmür. ədədi ədədinin kvadratsız hissəsi adlanır. Onu ilə işarə edək. Məsələn:

Teorem. a \cdot b hasili tam kvadratdır ancaq və ancaq sf[a] = sf[b] olduqda.

İsbat. Tutaq ki,

a = k_1 \cdot x_2, \\ b = k_2 \cdot y_2,

burada k_1 və k_2 kvadratsızdır. Onda

a * b = k_1k_2 \cdot (xy)^2

Bu ifadə tam kvadratdır ancaq və ancaq k_1k_2 tam kvadrat olduqda. Lakin k_1 və k_2 ədədləri kvadratsızdır. Deməli, k_1k_2 tam kvadrat olar yalnız k_1 = k_2 olduqda.

Qrupların sayılmasına gətirmə. Teoremdən belə nəticə çıxır ki, -dən -ə qədər olan ədədlər qiymətinə görə qruplara bölünür və cütü uyğun gəlir (a \cdot b tam kvadratdır) ancaq və ancaq və eyni qrupda yerləşdikdə.

Tutaq ki, sf[i] = k olan i~(1 \le i \le n) ədədlərinin sayına bərabərdir. Onu hesablamaq üçün hər bir üçün cnt[sf[i]]++ əməliyyatını yerinə yetirmək kifayətdir.

Əgər qrupda ədəd varsa, o zaman bu qrup

C_m^2 = \frac{m \cdot (m - 1)}{2}

cüt verir. Cavab bütün qruplar üzrə cəmə bərabərdir:

\sum_k \frac{cnt[k] \cdot(cnt[k] - 1)}{2}

Ən kiçik sadə bölən. -i sürətli hesablamaq üçün massivini daxil edək, bu massiv ədədinin ən kiçik sadə bölənini göstərir. Məsələn:

massivi Eratosfen ələyinin modifikasiya edilmiş üsulu ilə hesablanır: sadə ədədi emal edilərkən, -nin hər bir kratına (hələ təyin edilməmiş olarsa) spf[j] = p qiyməti mənimsədilir.

massivi olduqda, hər bir ədədin kvadratsız hissəsini hesablamaq olar. Tutaq ki, — ədədinin ən kiçik sadə bölənidir (spf[i] = p). İki hal nəzərdən keçirək:

sf[i] = sf[i / p^2]

Məsələn:

  1. sf[12] = sf[3], çünki spf[12] = 2 və ədədi 2^2-ə bölünür;

  2. = , çünki spf[45] = 3 və ədədi 3^2-ə bölünür;

sf[i] = sf[i / p] \cdot p

Məsələn:

  1. sf[30] = sf[15] \cdot 2, çünki spf[30] = 2 və ədədi 2^2-ə bölünmür;

  2. sf[18] = sf[9] \cdot 2, çünki spf[18] = 2 və ədədi 2^2-ə bölünmür;

Misal

n = 10 üçün cavabı hesablayaq.

i & vuruqlara ayrılma & kvadratsız hissə

& &

& &

& &

& 1 * 2^2 &

& &

& 2 * 3 &

& &

& 2 * 2^2 &

& 1 * 3^2 &

& 2 * 5 &

Ədədləri -ə görə massivində qruplaşdıraq.

cnt[1] = 3: (1, 4, 9) & cnt[6] = 1: (6)

cnt[2] = 2: (2, 8) & cnt[7] = 1: (7)

cnt[3] = 1: (3) & cnt[8] = 0: ()

cnt[4] = 0: () & cnt[9] = 0: ()

cnt[5] = 1: (5) & cnt[10] = 1: (10)

Cavab bərabərdir

\frac{cnt[1] \cdot (cnt[1] - 1)}{2} + \frac{cnt[2] \cdot (cnt[2] - 1)}{2} = \frac{3 \cdot 2}{2} + \frac{2 \cdot 1}{2} = 3 + 1 = 4

Alqoritmin realizasiyası

Sabitləri və massivləri elan edək.

#define MAXN 1000000
#define MOD 1000000007
int spf[MAXN + 1];     // ədədin minimal sadə böləni
int sf[MAXN + 1];      // ədədin kvadratsız hissələri
int cnt[MAXN + 1];     // verilmiş sf-ə malik ədədlərin sayı

giriş qiymətini oxuyuruq.

scanf("%d", \&n);

Eratosfen ələyi üsulunu tətbiq edərək, massivini doldururuq:

Əvvəlcə hər bir ədədin özünə bölündüyünü fərz edirik. Lakin bu müvəqqətidir.

for (i = 1; i \<= n; i++) spf[i] = i;

dəyişənində -dən \sqrt{n}-ə qədər ədədləri gəzirik.

for (i = 2; i * i \<= n; i++)
{
  if (spf[i] == i)
  {

Əgər ədədi sadədirsə, dəyişənində i^2, i^2 + i, i^2 + 2i, ... ədədlərini gəzirik. Bütün bu ədədlərin sadə böləni vardır (çünki spf[i] = i). Əgər spf[j] = j olarsa, onda ədədi üçün minimal sadə böləni yeniləyirik.

    for (j = i * i; j \<= n; j += i)
      if (spf[j] == j) spf[j] = i;
  }
}

Hər bir ədədi üçün onun kvadratsız hissəsini hesablayırıq. Nəticəni -ə yazırıq.

sf[1] = 1;
for (i = 2; i \<= n; i++)
{

dəyişəni ədədinin ən kiçik sadə bölənini saxlayır.

  p = spf[i];
  x = i / p;

Əgər ədədi p^2-ə bölünürsə, onda sf[i] = sf[i / p^2].

  if (x % p == 0)
    sf[i] = sf[x / p];

Əgər ədədi p^2-ə bölünmürsə (lakin -yə bölünür), onda sf[i] = sf[i / p] \cdot p.

  else
    sf[i] = sf[x] * p;
}

Ədədləri onların kvadratsız hissəsinə görə qruplaşdırırıq.

for (i = 1; i \<= n; i++)
  cnt[sf[i]]++;

Cavabı — axtarılan cütlərin sayını hesablayırıq.

res = 0;
for (i = 1; i \<= n; i++)
  if (cnt[i] \>= 2)
    res = (res + cnt[i] * (cnt[i] - 1) / 2) % MOD;

Cavabı çap edirik.

printf("%lld\n", res);