#!/usr/bin/perl -w use strict; my %f = ( 2 => 2, 3 => 1, 5 => 1, 11 => 1, 277412413 => 1 ); my @f = sort { $a <=> $b } keys %f; my @d = @f; my( %d, %x ); for my $i ( 0..$#f ) { my $f = $f[$i]; ( $d{$f} = [(0)x@f] )->[$i]++; $x{$f} = $i; } for my $i ( 0..$#f ) { my $f = $f[$i]; my $p = $f{$f}; my @t = @d; for my $e ( 1..$f{$f} ) { my( @t2, @m, @n ); while( @t ) { my $t = shift @t; merge( \@n, $t, \@m, 1 < $e ? \@d : () ); push @n, $t if 1 == $e; if( $d{$t}[$i] < $p && $x{$t} <= $i # Avoid duplicates ) { my $m = $t*$f; push @m, $m; push @t2, $m; ( $d{$m} = [@{ $d{$t} }] )->[$i]++; $x{$m} = $i if ! $x{$m} || $x{$m} < $i; } } @t = @t2; merge( \@n, 0, \@m, 1 < $e ? \@d : () ); @d = @n; } } print "Factors:"; for my $f ( @f ) { if( 1 < $f{$f} ) { print " $f^$f{$f}"; } else { print " $f"; } } print "\nDivisors: 1 @d\n"; exit; sub merge { my( $to_av, $max, $from_av, @rest ) = @_; if( $max ) { while( @$from_av && $from_av->[0] < $max ) { my $next = shift @$from_av; merge( $to_av, $next, @rest ) if @rest; push @$to_av, $next; } merge( $to_av, $max, @rest ) if @rest; } elsif( @rest ) { while( @$from_av ) { my $next = shift @$from_av; merge( $to_av, $next, @rest ); push @$to_av, $next; } merge( $to_av, 0, @rest ); } else { push @$to_av, @$from_av; @$from_av = (); } }