Ciao a te, andiamo per ordine:

1) la funzione scomposizione() non riuscirà mai a restituire al chiamante il parametro "l1" modificato, in quanto questo viene passato per valore e non per indirizzo. Quindi la tua funzione diventerà: list *scomposizione(int n, list **l) e sarà invocata con scomposizione(a, &l1) dalla funzione main()

2) la funzione scomposizione() per come è scritta non inizializza mai il primo elemento della lista (l'istruzione list *p=l; all'inizio del loop non funziona come forse ti immagini) e, di conseguenza, ogni elemento puntato dalla variabile p viene "perso" subito dopo l'inizializzazione con l'istruzione p=p->next; causando i cosiddetti "memory leaks" (o garbage, se preferisci). Una soluzione può essere la seguente:

codice:
list *scomposizione(int n, list **l)
{
int j;
list *p=NULL;   // <- puntatore all'elemento corrente
j = 2;
do
{
list *li=NULL;   // <- puntatore all'elemento in creazione
if(n % j == 0)
{
// qui alloco e inizializzo un nuovo elemento
	li=(list *)malloc(sizeof(list));
	li->num=j;
	li->next=NULL;
// faccio i calcoli
	n=n/j;

// se non esiste, il nuovo elemento diventa il primo elemento della lista...
	if (*l==NULL) *l=li;
// ...altrimenti il nuovo elemento diventa l'elemento successivo della lista...
	else p->next=li;
// ...e il nuovo elemento è anche l'elemento corrente
	p=li;
}
else
j++;
}
while (n > 1);
return *l;
}
Stefano.