Qualsiasi numero naturale è rappresentabile in modo unico nella forma i = k \cdot x^2, dove è libero da quadrati, cioè non è divisibile per il quadrato di alcun numero primo. Il numero si chiama parte libera da quadrati del numero . Lo indichiamo con . Ad esempio:
6 = 2 \cdot 3, quindi sf[6] = 6;
12 = 2^2 \cdot 3, quindi sf[12] = 3;
Teorema. Il prodotto a \cdot b è un quadrato perfetto se e solo se sf[a] = sf[b].
Dimostrazione. Siano
dove k_1 e k_2 sono liberi da quadrati. Allora
Questa espressione è un quadrato perfetto se e solo se k_1k_2 è un quadrato perfetto. Ma i numeri k_1 e k_2 sono liberi da quadrati. Di conseguenza k_1k_2 è un quadrato perfetto solo se k_1 = k_2.
Riduzione al conteggio dei gruppi. Dal teorema segue che i numeri da a si suddividono in gruppi in base al valore , e la coppia è valida (a \cdot b è un quadrato perfetto) se e solo se e appartengono allo stesso gruppo.
Sia uguale al numero di numeri i~(1 \le i \le n) per cui sf[i] = k. Per calcolarlo è sufficiente eseguire per ogni l'operazione cnt[sf[i]]++.
Se in un gruppo ci sono numeri, esso dà
coppie. La risposta è uguale alla somma su tutti i gruppi:
Divisore primo minimo. Per calcolare rapidamente introduciamo un array , uguale al minimo divisore primo del numero . Ad esempio:
L'array viene calcolato con un crivello di Eratostene modificato: durante l'elaborazione del numero primo , il valore spf[j] = p viene assegnato a ogni multiplo del numero , per il quale non è ancora stato impostato.
Avendo l'array , si può calcolare la parte libera da quadrati di ogni numero . Sia il minimo divisore primo del numero (spf[i] = p). Consideriamo due casi:
compare nella scomposizione del numero almeno due volte. Questo significa che il numero è divisibile per p^2. Due fattori primi uguali formano un quadrato perfetto, quindi possono essere esclusi dalla parte libera da quadrati:
Ad esempio:
sf[12] = sf[3], poiché spf[12] = 2 e è divisibile per 2^2;
= , poiché spf[45] = 3 e è divisibile per 3^2;
compare nella scomposizione del numero solo una volta. Quindi il fattore deve rimanere nella parte libera da quadrati:
Ad esempio:
sf[30] = sf[15] \cdot 2, poiché spf[30] = 2 e non è divisibile per 2^2;
sf[18] = sf[9] \cdot 2, poiché spf[18] = 2 e non è divisibile per 2^2;
Esempio
Calcoliamo la risposta per n = 10.
i | scomposizione in fattori | parte libera da quadrati |
1 * 2^2 | ||
2 * 3 | ||
2 * 2^2 | ||
1 * 3^2 | ||
2 * 5 |
Raggruppiamo i numeri nell'array in base a .
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) |
La risposta è uguale a
Implementazione dell'algoritmo
Dichiariamo le costanti e gli array.
#define MAXN 1000000
#define MOD 1000000007
int spf[MAXN + 1]; // divisore primo minimo del numero
int sf[MAXN + 1]; // parti libere da quadrati del numero
int cnt[MAXN + 1]; // quantità di numeri con un dato sfLeggiamo il valore di input .
scanf("%d", &n);Applicando il metodo del crivello di Eratostene, riempiamo l'array :
deve contenere il divisore primo minimo del numero
Inizialmente supponiamo che ogni numero sia divisibile per se stesso. Ma questo è temporaneo.
for (i = 1; i <= n; i++) spf[i] = i;Nella variabile scorriamo i numeri da a \sqrt{n}.
for (i = 2; i * i <= n; i++)
{
if (spf[i] == i)
{Se il numero è primo, nella variabile scorriamo i numeri i^2, i^2 + i, i^2 + 2i, ... . Tutti questi numeri hanno il divisore primo (poiché spf[i] = i). Se spf[j] = j, allora aggiorniamo il divisore primo minimo per il numero .
for (j = i * i; j <= n; j += i)
if (spf[j] == j) spf[j] = i;
}
}Per ogni numero calcoliamo la sua parte libera da quadrati. Il risultato lo inseriamo in .
sf[1] = 1;
for (i = 2; i <= n; i++)
{La variabile contiene il minimo divisore primo del numero .
p = spf[i];
x = i / p;Se è divisibile per p^2, allora sf[i] = sf[i / p^2].
if (x % p == 0)
sf[i] = sf[x / p];Se non è divisibile per p^2 (ma è divisibile per ), allora sf[i] = sf[i / p] \cdot p.
else
sf[i] = sf[x] * p;
}Raggruppiamo i numeri in base alla loro parte libera da quadrati.
for (i = 1; i <= n; i++)
cnt[sf[i]]++;Calcoliamo la risposta — il numero di coppie cercato.
res = 0;
for (i = 1; i <= n; i++)
if (cnt[i] >= 2)
res = (res + cnt[i] * (cnt[i] - 1) / 2) % MOD;Stampiamo la risposta.
printf("%lld\n", res);