The decision table
| Situation | Method | Cost |
|---|---|---|
| , one query | trial division to | |
| Many queries, all | linear sieve for the smallest prime factor | per query |
| Pollard’s rho + Miller-Rabin | ||
| has a medium factor, up to 60 digits | ECM | |
| 60-100 digit semiprime | Quadratic sieve | |
| > 100 digits | GNFS |
Trial division
vector<pair<long long,int>> factor(long long n) {
vector<pair<long long,int>> f;
for (long long p = 2; p * p <= n; p++) {
if (n % p) continue;
int e = 0;
while (n % p == 0) { n /= p; e++; }
f.push_back({p, e});
}
if (n > 1) f.push_back({n, 1}); // the remaining prime
return f;
}The final if is essential: after dividing out everything up to , whatever is left is a single prime (there can be at most one factor larger than ).
Smallest-prime-factor sieve — for many queries
vector<int> spf(N + 1);
for (int i = 2; i <= N; i++) {
if (!spf[i]) for (int j = i; j <= N; j += i) if (!spf[j]) spf[j] = i;
}
// factor in O(log n)
while (n > 1) { int p = spf[n]; int e = 0; while (n % p == 0) { n /= p; e++; } f.push_back({p,e}); }preprocessing, then each factorisation is — the right structure when the problem factors many numbers below .
Pollard’s rho + Miller-Rabin — the 64-bit answer
void factorRec(u64 n, map<u64,int>& f) {
if (n == 1) return;
if (isPrime(n)) { f[n]++; return; } // Miller-Rabin
u64 d = pollard(n);
factorRec(d, f);
factorRec(n / d, f);
}Strip small primes by trial division first (up to a few thousand) — it removes most of the work and avoids rho’s weakness on tiny factors. See Pollard’s Rho.
Expected , which factors any 64-bit number in microseconds.
What factorisation unlocks
Once you have :
| Quantity | Formula |
|---|---|
| Number of divisors | |
| Sum of divisors | |
| Euler totient | |
| Möbius | if any , else |
| All divisors | recursive product over exponents, of them |
| Carmichael | lcm of |
| Is a perfect square? | every even |
| Primitive root existence |
Counting and summing divisors without factoring
Number of divisors for every :
for (int i = 1; i <= N; i++)
for (int j = i; j <= N; j += i) d[j]++; — the harmonic series. The same loop with += i computes .
This “for each , loop over its multiples” pattern is the workhorse of divisor problems and is worth recognising: it is , not .
Divisor bounds
| max | |
|---|---|
| 240 | |
| 1344 | |
| 6720 | |
| 103 680 |
So “enumerate all divisors and do something per divisor” is affordable even for , provided you can factor .
Special forms
- — check each from 2 to , taking integer roots.
- Difference of squares () — Fermat’s method; fast when ‘s factors are close to , useless otherwise.
- — strip powers of two with
__builtin_ctzll. - Factorials and binomials — do not factor the number; use Legendre’s formula for the exponent of in .
See also: Pollard’s Rho · Divisor Functions · Sieve Techniques