Scomposizione in fattori#11611

Scomposizione in fattori (Editoriale)

Poiché è richiesto fattorizzare molti numeri non superiori a 10^7, conviene eseguire un precalcolo. Utilizzando una versione modificata del crivello di Eratostene, costruiamo l'array (smallest prime factor), dove

La fattorizzazione del numero viene eseguita nel modo seguente. Finché n > 1, prendiamo p = spf[n], il più piccolo divisore primo del valore corrente di , e dividiamo per finché la divisione risulta esatta, contando l'esponente. Successivamente stampiamo il fattore elevato alla potenza corrispondente e passiamo al divisore primo successivo. I fattori primi vengono così ottenuti in ordine crescente, il che corrisponde al formato di output richiesto.

La costruzione del crivello richiede un tempo O(n~log~log~n). Ogni divisione riduce di almeno la metà, quindi la fattorizzazione di un singolo numero viene eseguita in O(log~n). La complessità temporale totale per richieste è pari a O(n~log~log~n + q~log~n).

Implementazione dell'algoritmo

Dichiariamo l'array , in cui contiene il più piccolo divisore primo del numero .

#define MAX 10000001
int spf[MAX + 1];

La funzione Sieve implementa il crivello di Eratostene e riempie l'array .

void Sieve(int n)
{
  for (int i = 0; i < n; i++)
    spf[i] = i;
  for (int i = 2; i <= sqrt(n); i++)
    if (spf[i] == i)
      for (int j = i * i; j < n; j += i)
        if (spf[j] == j) spf[j] = i;
}

La funzione factorize scompone il numero nei suoi fattori primi, utilizzando l'array .

void factorize(int n)
{

Estraiamo i fattori primi dal numero finché esso è maggiore di .

  while (n > 1)
  {

Il più piccolo divisore primo del numero è uguale a .

    int p = spf[n];

Troviamo la potenza massima per cui p^{power} divide il numero .

    int power = 0;
    while (n % p == 0)
    {
      n /= p;
      power++;
    }

Stampiamo il fattore p^{power}.

    if (power > 1) printf("%d^%d", p, power); else printf("%d", p);

Tra i fattori va stampato il simbolo ''.

    if (n > 1) printf("*");
  }
  printf("\n");
}

Parte principale del programma. Riempiamo l'array utilizzando il crivello di Eratostene.

Sieve(MAX);

Per ogni valore di input stampiamo la sua scomposizione in fattori primi.

while (scanf("%d", &n) == 1)
  factorize(n);