from collections import Counter
import random
T = int ( input( ) )
def gcd( x, y) :
while y ! = 0 :
x, y = y, x % y
return x
def is_prime( N) :
if N == 1 : return False
if N == 2 or N == 3 or N == 5 : return True
if N % 2 == 0 or N % 3 == 0 or N % 5 == 0 : return False
q = N - 1
e = 0
while q % 2 == 0 :
q //= 2
e + = 1
for i in range( 10 ) :
r = random.randint ( 2 , N - 2 )
r = pow ( r, q, N)
if r == 1 : continue
for _ in range( e - 1 ) :
if r == N - 1 : break
r = r * r % N
if r == 1 : return False
if r ! = N - 1 : return False
return True
def f( N, phi) :
if N == 1 : return [ ]
if is_prime( N) : return [ N]
while phi % 2 == 0 : phi >>= 1 ;
while True:
r = random.randint ( 1 , N - 1 )
g = gcd( r, N)
if g ! = 1 : return f( N // g, phi) + f(g, phi)
r = pow ( r, phi, N)
while r * r % N ! = 1 :
r = r * r % N
if r ! = 1 and r ! = N - 1 :
h = gcd( r - 1 , N)
return f( N // h, phi) + f(h, phi)
def ff( N, phi) :
g = gcd( N, phi)
if g == 1 or g == N: return f( N, phi)
ans = f( N // g, phi)
for p in ans[ : ] :
e = 0
while N % p == 0 :
N //= p
e + = 1
while g % p == 0 :
g //= p
ans.append ( p)
for _ in range( e - 1 ) :
phi //= p
phi //= p - 1
return ff( N, phi) + ans
for _ in range( T) :
N, phi = map( int , input( ) .split ( ) )
ans = ff( N, phi)
ans = dict( Counter( ans) )
print( len( ans) )
for k in sorted( ans.keys ( ) ) :
print( k, ans[ k] )
ZnJvbSBjb2xsZWN0aW9ucyBpbXBvcnQgQ291bnRlcgppbXBvcnQgcmFuZG9tCgpUID0gaW50KGlucHV0KCkpCgpkZWYgZ2NkKHgsIHkpOgogIHdoaWxlIHkgIT0gMDoKICAgIHgsIHkgPSB5LCB4ICUgeQogIHJldHVybiB4CgpkZWYgaXNfcHJpbWUoTik6CiAgaWYgTiA9PSAxOiByZXR1cm4gRmFsc2UKICBpZiBOID09IDIgb3IgTiA9PSAzIG9yIE4gPT0gNTogcmV0dXJuIFRydWUKICBpZiBOICUgMiA9PSAwIG9yIE4gJSAzID09IDAgb3IgTiAlIDUgPT0gMDogcmV0dXJuIEZhbHNlCiAgcSA9IE4gLSAxCiAgZSA9IDAKICB3aGlsZSBxICUgMiA9PSAwOgogICAgcSAvLz0gMgogICAgZSArPSAxCiAgZm9yIGkgaW4gcmFuZ2UoMTApOgogICAgciA9IHJhbmRvbS5yYW5kaW50KDIsIE4gLSAyKQogICAgciA9IHBvdyhyLCBxLCBOKQogICAgaWYgciA9PSAxOiBjb250aW51ZQogICAgZm9yIF8gaW4gcmFuZ2UoZSAtIDEpOgogICAgICBpZiByID09IE4gLSAxOiBicmVhawogICAgICByID0gciAqIHIgJSBOCiAgICAgIGlmIHIgPT0gMTogcmV0dXJuIEZhbHNlCiAgICBpZiByICE9IE4gLSAxOiByZXR1cm4gRmFsc2UKICByZXR1cm4gVHJ1ZQoKZGVmIGYoTiwgcGhpKToKICBpZiBOID09IDE6IHJldHVybiBbXQogIGlmIGlzX3ByaW1lKE4pOiByZXR1cm4gW05dCiAgd2hpbGUgcGhpICUgMiA9PSAwOiBwaGkgPj49IDE7CiAgd2hpbGUgVHJ1ZToKICAgIHIgPSByYW5kb20ucmFuZGludCgxLCBOIC0gMSkKICAgIGcgPSBnY2QociwgTikKICAgIGlmIGcgIT0gMTogcmV0dXJuIGYoTiAvLyBnLCBwaGkpICsgZihnLCBwaGkpCiAgICByID0gcG93KHIsIHBoaSwgTikKICAgIHdoaWxlIHIgKiByICUgTiAhPSAxOgogICAgICByID0gciAqIHIgJSBOCiAgICBpZiByICE9IDEgYW5kIHIgIT0gTiAtIDE6CiAgICAgIGggPSBnY2QociAtIDEsIE4pCiAgICAgIHJldHVybiBmKE4gLy8gaCwgcGhpKSArIGYoaCwgcGhpKQoKZGVmIGZmKE4sIHBoaSk6CiAgZyA9IGdjZChOLCBwaGkpCiAgaWYgZyA9PSAxIG9yIGcgPT0gTjogcmV0dXJuIGYoTiwgcGhpKQogIGFucyA9IGYoTiAvLyBnLCBwaGkpCiAgZm9yIHAgaW4gYW5zWzpdOgogICAgZSA9IDAKICAgIHdoaWxlIE4gJSBwID09IDA6CiAgICAgIE4gLy89IHAKICAgICAgZSArPSAxCiAgICB3aGlsZSBnICUgcCA9PSAwOgogICAgICBnIC8vPSBwCiAgICAgIGFucy5hcHBlbmQocCkKICAgIGZvciBfIGluIHJhbmdlKGUgLSAxKToKICAgICAgcGhpIC8vPSBwCiAgICBwaGkgLy89IHAgLSAxCiAgcmV0dXJuIGZmKE4sIHBoaSkgKyBhbnMKCmZvciBfIGluIHJhbmdlKFQpOgogIE4sIHBoaSA9IG1hcChpbnQsIGlucHV0KCkuc3BsaXQoKSkKICBhbnMgPSBmZihOLCBwaGkpCiAgYW5zID0gZGljdChDb3VudGVyKGFucykpCiAgcHJpbnQobGVuKGFucykpCiAgZm9yIGsgaW4gc29ydGVkKGFucy5rZXlzKCkpOgogICAgcHJpbnQoaywgYW5zW2tdKQ==