Perché le espressioni le valuta da sinistra a destra.
Intanto "(UL)" è proprio errato, non compila neanche perché non è un tipo ma solo un indicatore per il compilatore per gestire correttamente il valore costante che lo precede. Quindi non "UL" ma "uint32_t" (o "unsigned long").
Poi la prima moltiplicazione lui la fa tra interi, e 900*900, che farebbe 810.000, viene calcolato su uint16 quindi va in overflow restituendo 23.568, che moltiplicato per l'unsigned long 2.000 dà 47.136.000.
Nella seconda e nell'ultima parte già come unsigned long o uint32_t, quindi effettua correttamente tutti i passaggi come unsigned long.
EDIT: nota che il cast dell'ultima espressione si applica solo al primo valore, ossia diciamo che equivale a:
Esatto. Con o senza quel cast, il risultato non cambia anche perché quel cast è addirittura inutile perché automatico quando assegni un valore di un tipo, anche se ottenuto da una espressione, ad una variabile di un altro tipo.
Purtroppo sono cose non molto "visibili" ma le capisci solo quando ci "sbatti la faccia" (io l'ho imparato proprio così ).