#dc, 96 bytes
?sbsa2sf[q]sk[lalf~lblf~szrlz+0<ksbsale1+selsx]ss[lfn[^]Plen[ ]P]sp[0selsxle0<plf1+dsflb!<w]dswx
It reads one line of standard input. Its output does not end with a newline. Example:
$ echo 301343045 421880263 | dc factorize.dc
1021^1 59029^1 $
Code with comments:
# dc(1) is a stack language, like Forth. Programs push values on the
# stack, then operate on them. For example, to calculate
# (2 + 3) * (9 - 4)
# the dc code is
# [2 3 + 9 4 - *]
# [?] reads a line of input. We expect two integers >= 2.
# [sb sa] stores the integers in variables.
? sb sa # a, b = two integers from input
# This program sucks common factors from a and b, looping for
# f = 2, 3, 4, 5, and so on. This method only sucks prime factors,
# but wastes time when f is not prime.
2 sf # f = 2
# Code in [...] does not run until the program calls it.
# k = code to break a loop
[
q # [q] breaks two levels of [...]
] sk # k = break
# s = loop to suck factor f from a and b
# This loop increments e, the exponent for factor f.
# Please set e = 0 before entering this loop.
[
# [la lf] puts ( a f ) on the stack.
# [~] does division and remainder.
# STACK:
la lf ~ # ( a/f a%f )
lb lf ~ # ( a/f a%f b/f b%f )
# [r] swaps the top two stack values.
# Hold z = b%f and swap a%f with b/f.
# STACK:
sz r lz # ( a/f b/f a%f b%f )
# f is a common factor if a%f and b%f are zero. Because a and b are
# non-negative, a%f and b%f are zero only if a%f+b%f is zero.
# STACK:
+ # ( a/f b/f a%f+b%f )
# Call k to break loop unless a%f+b%f is zero. [<k] conditionally
# calls k if the comparison is true. Comparisons in dc are
# backwards, so [3 0 <k] would check 0 < 3. Because a%f+b%f is never
# negative, [0 <k] is golf for [0 !=k].
# STACK:
0 <k # ( a/f b/f )
# f is a common factor, so suck it!
sb sa # a = a/f, b = b/f, STACK: ( )
le 1 + se # increment e, the exponent for this factor
ls x # continue loop, [x] executes s
] ss # s = loop
# p = code to print "f^e "
[
# [n] prints a number without a newline.
# [P] prints a string.
lf n [^]P
le n [ ]P
# DEBUG: Uncomment to print a and b.
#[(a = ]P la n [, b = ]P lb n [)]P 10P
] sp # p = print
# w = loop to iterate factors
[
# Call s loop to suck factor f from a and b, and set exponent e.
0 se # e = 0
ls x # call s loop
# DEBUG: Uncomment [c] to clear the stack. Loop s leaves two junk
# values ( a/f b/f ) on the stack. Deleting [c] for code golf saves
# 1 byte but leaks junk on the stack.
#c
# Print "f^e " if 0 < e. Comparisons in dc are backwards, so
# [0 le <p] would check e < 0, [le 0 <p] checks 0 < e.
le 0 <p
# Increment f. [d] duplicates top value on stack.
# STACK:
lf 1 + # ( f+1 )
d # ( f+1 f+1 )
sf # ( f ) as f+1 becomes f
# Continue loop if b >= f. This is golf for f <= a and f <= b, as
# extra iterations of the loop cause no harm.
# STACK:
lb # ( f b )
!<w # ( ), continue loop if not b < f
] d sw # w = loop; STACK: ( w )
x # enter loop unconditionally; STACK: ( ) at entrance