from fractions import gcd
from operator import mul
import random
import itertools
MAXLOOKUP=1000000
MAXSMALLPRIME=300
# prime_or_factor[n]==0 indicates n is a prime,
# otherwise prime_or_factor[n] holds a prime factor of n
prime_or_factor=[0]*(MAXLOOKUP+1)
max_p = int(MAXLOOKUP**0.5)+1
prime_or_factor[4::2]=[2]*len(prime_or_factor[4::2])
prime_or_factor[9::6]=[3]*len(prime_or_factor[9::6])
p=5
while (p <= max_p):
if prime_or_factor[p]==0:
prime_or_factor[p*p::2*p]=[p]*len(prime_or_factor[p*p::2*p])
if p%6==5:
p+=2
else:
p+=4
smallprimes = [p for p in range(2,MAXSMALLPRIME) if prime_or_factor[p]==0]
def all_factors( x ):
if type(x)==list:
allf = [1]
for p in set(x):
e=x.count(p)
le = len(allf)
pn = 1
for i in range(e):
pn *= p
allf.extend([a*pn for a in allf[0:le] ])
return allf
elif type(x)==int or type(x)==long:
return all_factors(factorise(x))
#-----------------------------------------------
#-----------------------------------------------
def factorise_trial_division(n):
if n==1:
return []
factors=[]
for p in (2,3):
while n%p==0:
factors.append(p)
n //= p
q=5
while q*q <= n:
for p in (q,q+2):
while n%p==0:
factors.append(p)
n //= p
q+=6
if n>1:
factors.append(n)
return factors
#-----------------------------------------------
def factorise_lookup(n):
i = prime_or_factor[n]
f=[]
while i :
f.append(i)
n//=i
i = prime_or_factor[n]
if n>1:
f.append(n)
return f
#-----------------------------------------------
def brent(N,maxBrentTime=1.0):
if N%2==0:
return 2
# http://xn--2-umb.com/09/12/brent-pollard-rho-factorisation suggests that
# m=1000 is the optimum value
y,c,m = random.randint(1, N-1),random.randint(1, N-1), 200
g,r,q = 1,1,1
while g==1:
x = y
for _ in range(r):
y = (y*y+c)%N
k = 0
while (k<r and g==1):
ys = y
for _ in range(min(m,r-k)):
y = (y*y+c)%N
q = q*(abs(x-y))%N
g = gcd(q,N)
k += m
r = r*2
if g==N:
while True:
ys = (ys*ys+c)%N
g = gcd(abs(x-ys),N)
if g>1:
break
return g
#-----------------------------------------------
def millerRabin(n, factor=[1]):
global factorFromMillerRabin
if n == 2: return True
if n<2: return False
if n%2==0:
factor[0]=2
return False
two64 = pow(2,64)
if n < 2047: P=(2,)
elif n < 1373653: P=(2,3)
elif n < 9080191: P=(31,73)
elif n < 4759123141: P=(2,7,61)
elif n < 2152302898747: P=(2,3,5,7,11)
elif n < 3474749660383: P=(2,3,5,7,11,13)
elif n < 341550071728321: P=(2,3,5,7,11,13,17)
elif n < 3825123056546413051: P=(2,3,5,7,11,13,17,19,23)
elif n < two64: P=(2, 325, 9375, 28178, 450775, 9780504, 1795265022) #http://miller-rabin.appspot.com/
else: P=[2,3,5,7,11,13,17,19,23]+[random.randint(24,n-2) for i in range(40)]
if n < 3825123056546413051 and n in P: return True
# find s,d so that d is odd and (2^s)d = n-1
d = (n-1)>>1
s = 1
while d&1 == 0:
d >>= 1
s += 1
for w in P:
a = pow(w, d, n)
if a == 1: continue
r = 0
while r < s:
if a == n-1: break
prev_a = a
a = (a*a)%n
if a==1:
# Previous value of a was a square root of unity not equal to -1.
# We can use this to find a factor of n
factor[0]=gcd(prev_a - 1, n)
return False
r += 1
if r == s:
# If we arrive here, then a^(n-1) != 1 mod n,
# so n cannot be a prime, but we can't find a factor of n
factor[0]=1
return False
return True
#-----------------------------------------------
def factorise_large(n, maxBrentTime=1.0):
brent_failures = 0
brent_calls = 0
brent_avoid = 0
if n <= MAXLOOKUP:
return factorise_lookup(n)
millerrabinfactor = [1]
if millerRabin(n,millerrabinfactor):
return [n]
if 1 < millerrabinfactor[0] < n :
p = millerrabinfactor[0]
brent_avoid+=1
else:
p=brent(n, maxBrentTime)
brent_calls+=1
q=n//p
if p>q:
p,q = q,p
if p==1:
if millerRabin(q):
return [q]
else:
brent_failures+=1
return factorise_large(q, maxBrentTime) # Try again (sometimes brent doesn't find factors)
else:
return factorise_large(p)+factorise_large(q)
#-----------------------------------------------
# utility functions that a user can call
#-----------------------------------------------
def factorise(n, maxBrentTime=1.0):
if n<=MAXLOOKUP:
return factorise_lookup(n)
factors=[]
for p in smallprimes:
while n%p==0:
factors.append(p)
n//=p
if n ==1:
return factors
return factors + factorise_large(n, maxBrentTime)
def totient(n):
f = factorise(n)
t=1
for x in set(f):
t*=pow(x,f.count(x)-1)*(x-1)
return t
def unfactorise( d ):
return reduce(mul, d, 1)
def radical( d ):
if type(d)==list:
return reduce(mul, set(d), 1)
else:
return reduce(mul, set(factorise(d)), 1)
#-----------------------------------------------
num_probs = int(input())
for _ in range(num_probs):
n = int(input())
f = factorise(n)
#print(n, f)
rv = 1
primes = 0
for x in set(f):
primes += 1
rv *= (1 + f.count(x))
print(rv - primes)
Language: Python 3