Smaller number-theoretic tools: intersections of arithmetic progressions, coprime bases, Pythagorean triples, counting square roots of 1 and -th powers, residues of in a range, Fibonacci numbers, power towers, balanced ternary and NAF, elliptic curves over , and Gaussian integers. Dependencies from other notes: extgcd, invMod (GCD), crtMerge, crt, garner, diophantine, countSolutions (Congruences and CRT), floorSum (Floor Sums), power (Modular Arithmetic, used by PowerTower and twoSquares); the simplest fraction in an interval is simplestBetween in Big Integers and Fractions.
| Function | Answers | Cost |
|---|---|---|
apIntersection(a1, d1, a2, d2) | () as first + step * t | |
coprimeBasis(vals) | pairwise coprime numbers that generate every value multiplicatively | |
forEachPythagorean(N, f) | all primitive , | |
countSquareRootsOfOne(m) | ||
countKthPowers(n, k) | ||
countResiduesInRange(a, b, m, n, lo, hi) | by floor sums |
pair<ll, ll> apIntersection(ll a1, ll d1, ll a2, ll d2) { // d1, d2 >= 1; returns {first, step}, first = -1 if empty
auto [x, l] = crtMerge(((a1 % d1) + d1) % d1, d1, ((a2 % d2) + d2) % d2, d2);
if (x < 0) return {-1, -1};
ll lo = max(a1, a2); // first common element >= both starting points
if (x < lo) x += (lo - x + l - 1) / l * l;
return {x, l};
}
vector<ll> coprimeBasis(const vector<ll>& vals) { // values >= 1
vector<ll> basis;
for (ll v : vals) {
vector<ll> work{v};
while (!work.empty()) {
ll x = work.back(); work.pop_back();
if (x == 1) continue;
bool split = false;
for (int i = 0; i < sz(basis); i++) {
ll g = gcd(basis[i], x);
if (g == 1) continue;
ll b = basis[i]; basis.erase(basis.begin() + i);
work.push_back(g); work.push_back(b / g); work.push_back(x / g);
split = true; break;
}
if (!split) basis.push_back(x);
}
}
sort(all(basis)); basis.erase(unique(all(basis)), basis.end());
return basis;
}
template<class F> void forEachPythagorean(ll N, F f) { // primitive triples (a, b, c), c <= N
for (ll m = 2; m * m + 1 <= N; m++)
for (ll k = 1 + (m % 2); k < m && m * m + k * k <= N; k += 2)
if (gcd(m, k) == 1) f(m * m - k * k, 2 * m * k, m * m + k * k);
}
ll countSquareRootsOfOne(ll m) {
ll res = 1;
for (ll p = 2; p * p <= m; p++) {
if (m % p) continue;
int e = 0; while (m % p == 0) m /= p, e++;
res *= p == 2 ? (e == 1 ? 1 : e == 2 ? 2 : 4) : 2;
}
if (m > 1) res *= m == 2 ? 1 : 2;
return res;
}
ll countKthPowers(ll n, ll k) { // k >= 1; values of a^k mod n, including 0 and non-units
auto ipow = [](ll b, ll e) { ll r = 1; while (e-- > 0) r *= b; return r; };
auto f = [&](auto&& self, ll p, ll e) -> ll { // count modulo p^e
if (e <= 0) return 1; // only 0
if (p == 2) {
if (e == 1) return 2;
ll u = ipow(2, e - 2) / gcd(k, ipow(2, e - 2));
if (k % 2) u *= 2;
return u + self(self, 2, e - k);
}
ll phi = ipow(p, e) - ipow(p, e - 1);
return phi / gcd(k, phi) + self(self, p, e - k);
};
ll res = 1, x = n;
for (ll p = 2; p * p <= x; p++) { if (x % p) continue; int e = 0; while (x % p == 0) x /= p, e++; res *= f(f, p, e); }
if (x > 1) res *= f(f, x, 1);
return res;
}
ll countResiduesInRange(ll a, ll b, ll m, ll n, ll lo, ll hi) { // 0 <= lo <= hi <= m
a = ((a % m) + m) % m; b = ((b % m) + m) % m;
auto below = [&](ll t) -> ll { // #i with (a i + b) mod m < t
if (t <= 0) return 0;
if (t >= m) return n;
return n - (floorSum(n, m, a, b + m - t) - floorSum(n, m, a, b));
};
return below(hi) - below(lo);
}Proof: the miscellany functions
AP intersection. lies in both progressions (ignoring ) iff and , which by the generalized CRT is empty or one class modulo ; the smallest member is the first common element with in both.
Coprime basis. Invariant: the product of all numbers in
basisandwork(with multiplicity) generates, multiplicatively, every processed value, andbasisis pairwise coprime. Splitting and with into keeps generation (, ) and replaces two numbers of product by three of product (ones are dropped), so the product of everything inbasisandworkstrictly decreases and the process terminates; an element is appended only when it is coprime to the whole basis.Pythagorean triples (Euclid). For a primitive triple, exactly one of is even (squares are , so two odd legs would make ); with even, with coprime factors, so both are squares : , , with , , odd; conversely these are primitive. Each triple arises once.
Square roots of 1. By the CRT, count per prime power. For odd , and cannot divide both factors (their difference is 2), so : 2 roots. Modulo : 1 root for , 2 for (), and 4 for (, ), since both factors are even and one must be divisible by .
-th powers modulo . Write with a unit. Units: for odd the unit group is cyclic of order , and the image of has elements. For , , the units are : the image has elements times 2 if is odd (the part survives). Multiples of : gives , and multiplication by is injective from into , so these values correspond one-to-one to the -th powers modulo (all residues there, including 0): the recursion
self(p, e - k), with leaving only 0. By the CRT the counts multiply over prime powers. Checked by brute force for all and .Residues in a range. For an integer and : is 1 if and 0 otherwise. Summing over , , gives as a difference of two floor sums; subtract from . All functions were checked against brute force on random inputs.
Fibonacci numbers
, , ; (); is the last that fits in long long, the last in unsigned long long.
| Method | Time | Use |
|---|---|---|
| iteration | ||
| matrix power | ||
| fast doubling | same, about 2 times faster, no matrix struct | |
| Binet | inexact beyond |
| Identity | |
|---|---|
| addition formula | |
| , | doubling |
| , hence | strong divisibility: common factors of Fibonacci numbers become gcds of indices |
| Cassini | |
| Lucas numbers , : , |
| Pisano period ( is periodic) | |
|---|---|
| multiplicative structure | |
| , with equality iff | (known theorem) |
| conjectured always (Wall), verified far | |
| : ; : | from or |
| , , | so |
Zeckendorf: every positive integer is uniquely a sum of non-consecutive Fibonacci numbers (greedy: take the largest that fits); it underlies Wythoff’s game, Fibonacci coding (self-delimiting codes) and “no two adjacent terms” representations.
| Where Fibonacci appears | Count |
|---|---|
| binary strings of length with no two adjacent 1s; subsets of with no two consecutive | |
| domino tilings of ; stairs climbed 1 or 2 at a time | |
| worst case of the Euclidean algorithm | consecutive Fibonacci inputs |
| golden-section search, minimum AVL tree of height | ratio , nodes |
| tribonacci / -bonacci | matrix power, or Bostan–Mori: Linear Recurrences |
pair<ll, ll> fibPair(ll n, ll mod) { // {F(n) mod m, F(n+1) mod m}, fast doubling
if (n == 0) return {0, 1 % mod};
auto [a, b] = fibPair(n >> 1, mod);
ll c = (ll)((i128)a * ((2 * b - a + mod) % mod) % mod); // F(2k)
ll d = (ll)(((i128)a * a + (i128)b * b) % mod); // F(2k+1)
return n & 1 ? pair{d, (c + d) % mod} : pair{c, d};
}
vector<ll> zeckendorf(ll n) { // n >= 1: non-consecutive Fibonacci terms, decreasing
vector<ll> f{1, 2}; while (f.back() <= n - f[sz(f) - 2]) f.push_back(f.back() + f[sz(f) - 2]);
vector<ll> res;
for (int i = sz(f) - 1; i >= 0 && n > 0; i--) if (f[i] <= n) res.push_back(f[i]), n -= f[i];
return res;
}Proof: the doubling formulas, strong divisibility, Cassini, sums and Zeckendorf
Addition and doubling. by induction; comparing entries of gives . With : ; with , : . Cassini: . Sums: by induction (); since .
Strong divisibility. Consecutive Fibonacci numbers are coprime (a common divisor of divides all earlier terms, down to ). From the addition formula, , so (as ). Thus follows the Euclidean algorithm on the indices and ends at .
Zeckendorf. Existence: greedy takes the largest ; the remainder is , so the next term chosen is not adjacent. Uniqueness: a sum of non-consecutive Fibonacci numbers with largest term is less than (induction: ); so the largest term of any representation of must be the largest Fibonacci number , and induct. Pisano: is determined by the pair , which is invertible as a recurrence, so the sequence is purely periodic, and the period of the pair modulo is the lcm of the periods (CRT). The bound and the divisibility facts are quoted; checked numerically for , together with the fast doubling and Zeckendorf code.
Power towers
for any modulus (no coprimality): use whenever , and decide “is the exponent at least ?” from the exact value capped at , which a tower of more than five numbers always exceeds. The modulus chain reaches 1 within levels. Classic: Codeforces 906D Power Tower. Cost: levels, each for (memoized) plus for the power. (The folklore version that stores ” if , else ” can lose the "" information after an exponent has been reduced; carrying the capped exact value avoids that question.)
struct PowerTower { // uses power(a, e, m) from Modular Arithmetic
static constexpr ll CAP = 1LL << 62;
vector<ll> a; vector<int> nextOne; map<ll, ll> phiMemo;
PowerTower(const vector<ll>& a) : a(a), nextOne(sz(a) + 1, sz(a)) { // a_i >= 1
for (int i = sz(a) - 1; i >= 0; i--) nextOne[i] = a[i] == 1 ? i : nextOne[i + 1];
}
ll phi(ll n) {
auto it = phiMemo.find(n); if (it != phiMemo.end()) return it->second;
ll res = n, m = n;
for (ll p = 2; p * p <= m; p++) if (m % p == 0) { while (m % p == 0) m /= p; res = res / p * (p - 1); }
if (m > 1) res = res / m * (m - 1);
return phiMemo[n] = res;
}
static ll satPow(ll b, ll e) { ll r = 1; while (e-- > 0 && b > 1) { if (r > CAP / b) return CAP; r *= b; } return r; }
ll capped(int l, int r) { // min(tower a[l..r], CAP)
int k = min(nextOne[l], r); // a 1 at k makes everything above it irrelevant
if (k - l >= 6) return CAP; // at least 6 numbers >= 2: beyond 2^62
ll v = min(a[k], CAP);
for (int i = k - 1; i >= l; i--) v = satPow(a[i], min(v, 64LL));
return v;
}
ll tower(int l, int r, ll m) { // a[l..r] as a tower, mod m
if (m == 1) return 0;
if (l == r) return a[l] % m;
ll ph = phi(m), ec = capped(l + 1, r);
ll e = ec < ph ? ec : tower(l + 1, r, ph) + ph; // exact exponent, or an equivalent one >= phi(m)
return power(a[l], e, m);
}
};Proof: the generalized Euler theorem and the capped tower
Claim: if and , then for every . By the CRT it suffices modulo each prime power , using . If , Euler gives , and is a multiple of . If , then for every , and both exponents are .
The code.
cappedreturns the exact tower value when it is below , and otherwise: above a 1 nothing matters (); six or more numbers give at least ; otherwise the at most six levels are evaluated from the top with saturation (an exponent on a base saturates). Intower, if the capped exponent is below it is the exact exponent and the power is exact modulo . Otherwise the true exponent is , the recursive call gives , and satisfies the claim’s hypotheses with . Since is even for and of an even number is at most half of it, the modulus at least halves every two levels: levels. Checked against exact evaluation on random towers whose true exponent fits in 64 bits, including bases 1.
Balanced ternary and non-adjacent form
Base 3 with digits : every integer, positive or negative, has a unique representation without a sign (, , ). Conversion: take ; a 2 becomes with a carry. Bachet’s balance: weights , each on the empty pan (), with the object () or unused (), weigh every integer mass up to (Bachet’s Weights). The Soviet Setun computer (1958) used balanced ternary.
| Property | |
|---|---|
| representation | unique for every integer |
| negation | flip every digit; no two’s-complement asymmetry |
| sign | carried by the leading digit |
| rounding | truncation gives the nearest value |
| range of digits | , symmetric |
| digits needed | about $\log_3(2 |
| Problem | Why balanced ternary |
|---|---|
| weigh any mass with weights | the defining example |
| as with distinct exponents | exactly the representation (always possible, uniquely) |
| games where each move is | state = digits |
| minimum number of signed powers of 3 summing to | the number of non-zero digits |
| ternary search trees, three-way partition | the three-outcome analogy |
Non-adjacent form (NAF): base 2 with digits and no two adjacent non-zero digits; unique, of minimal weight, with on average one third of the digits non-zero (versus one half in binary): exponentiation and elliptic-curve scalar multiplication get about 11% faster (fewer multiplications; subtraction of a point is as cheap as addition). Related systems: binary, Zeckendorf (Fibonacci base, no two adjacent 1s), factorial base (digit in ; permutation ranking via the Lehmer code), Gray code (consecutive values differ in one bit), negabinary (base , negatives without a sign): Modular Arithmetic has negative bases and fromBalancedTernary.
vector<int> toBalancedTernary(ll n) { // least significant digit first, digits in {-1, 0, 1}
vector<int> d;
while (n) {
int r = int(((n % 3) + 3) % 3);
if (r == 2) { d.push_back(-1); n = (n + 1) / 3; } // exact division
else { d.push_back(r); n = (n - r) / 3; }
}
return d;
}
vector<int> naf(ll n) { // n >= 0, least significant first, no two adjacent non-zeros
vector<int> d;
while (n) {
if (n & 1) { int z = 2 - int(n % 4); d.push_back(z); n -= z; } // z = 1 if n = 1 mod 4, -1 if n = 3 mod 4
else d.push_back(0);
n >>= 1;
}
return d;
}Proof: balanced ternary and NAF are unique, and NAF density is 1/3
Balanced ternary. The last digit must be and lie in , so it is forced (); then is an integer of smaller absolute value (for ) and we recurse: existence and uniqueness by induction on . With digits the extremes are , and there are exactly digit strings for the integers in that range. NAF. If is even the digit is 0. If is odd the digit is chosen with , so the next digit is 0: no two adjacent non-zeros. Uniqueness: an odd forces and the non-adjacency forces even, which determines . Density: after a non-zero digit the next is 0, and then each bit is odd with probability independently (for random ), so the gap to the next non-zero digit is , mean 3: one non-zero digit per 3 positions. Binary exponentiation then costs about squarings and multiplications instead of : less work. Checked: reconstruction and the digit constraints for all .
Elliptic curves over
Points of ( prime, ) plus the point at infinity form an abelian group under the chord-and-tangent law: slope , or when doubling; . Hasse: . Scalar multiplication by double-and-add is the one-way function of elliptic-curve cryptography (the discrete logarithm is hard), and Lenstra’s factorization runs the same arithmetic modulo a composite , succeeding when an inversion fails (Theoretical Algorithms). Cost: per addition (one inverse), per multiplication, point counting by Euler’s criterion.
struct ECPoint {
ll x = 0, y = 0; bool inf = false;
static ECPoint infinity() { return {0, 0, true}; }
bool operator==(const ECPoint& o) const { return inf == o.inf && (inf || (x == o.x && y == o.y)); }
};
struct EllipticCurve {
ll a, b, p;
EllipticCurve(ll a_, ll b_, ll p_) : a((a_ % p_ + p_) % p_), b((b_ % p_ + p_) % p_), p(p_) {}
ll mul(ll x, ll y) const { return (ll)((i128)x * y % p); }
ll pw(ll x, ll e) const { ll r = 1; for (x %= p; e; e >>= 1, x = mul(x, x)) if (e & 1) r = mul(r, x); return r; }
ll inv(ll x) const { return pw(x, p - 2); }
bool contains(const ECPoint& P) const { return P.inf || mul(P.y, P.y) == (mul(mul(P.x, P.x), P.x) + mul(a, P.x) + b) % p; }
ECPoint add(const ECPoint& P, const ECPoint& Q) const {
if (P.inf) return Q;
if (Q.inf) return P;
ll s;
if (P.x == Q.x) {
if ((P.y + Q.y) % p == 0) return ECPoint::infinity();
s = mul((3 * mul(P.x, P.x) + a) % p, inv(2 * P.y % p));
} else s = mul(((Q.y - P.y) % p + p) % p, inv(((Q.x - P.x) % p + p) % p));
ll x = ((mul(s, s) - P.x - Q.x) % p + 2 * p) % p;
ll y = ((mul(s, (P.x - x + p) % p) - P.y) % p + p) % p;
return {x, y, false};
}
ECPoint negate(const ECPoint& P) const { return P.inf ? P : ECPoint{P.x, (p - P.y) % p, false}; }
ECPoint multiply(ECPoint P, ll k) const { ECPoint R = ECPoint::infinity(); for (; k > 0; k >>= 1, P = add(P, P)) if (k & 1) R = add(R, P); return R; }
ll countPoints() const { // including infinity
ll cnt = 1;
for (ll x = 0; x < p; x++) { ll rhs = (mul(mul(x, x), x) + mul(a, x) + b) % p; cnt += rhs == 0 ? 1 : pw(rhs, (p - 1) / 2) == 1 ? 2 : 0; }
return cnt;
}
};Proof: the formulas and the point count
The line through (or the tangent at ) meets the cubic in a third point ; substituting into gives a monic cubic in whose roots sum to , so , and is the reflection of : . The tangent slope comes from implicit differentiation, . A vertical line (, ) meets the curve at infinity: . Associativity and Hasse’s bound are classical theorems (quoted). Counting: for each , has 1 solution if , 2 if is a non-zero square (Euler: ) and 0 otherwise. Checked: associativity, commutativity and the identity on random points of random curves,
multiplyagainst repeated addition,countPointsagainst brute force over all , and Hasse’s bound.
Gaussian integers
with norm is a Euclidean domain (rounding each coordinate of leaves a remainder of norm ), so Euclid’s algorithm computes gcds. Units: . Primes: ; rational primes ; and the two factors of each . This gives an two-square decomposition once is known, and the representation count (with for ).
struct GI { ll a, b; }; // a + b i (keep norms below about 4e18)
GI operator-(GI x, GI y) { return {x.a - y.a, x.b - y.b}; }
GI operator*(GI x, GI y) { return {x.a * y.a - x.b * y.b, x.a * y.b + x.b * y.a}; }
ll roundDiv(i128 n, i128 d) { return (ll)(n >= 0 ? (2 * n + d) / (2 * d) : -((-2 * n + d) / (2 * d))); } // d > 0
GI gquot(GI x, GI y) { // nearest Gaussian integer to x / y
i128 nn = (i128)y.a * y.a + (i128)y.b * y.b;
i128 re = (i128)x.a * y.a + (i128)x.b * y.b, im = (i128)x.b * y.a - (i128)x.a * y.b;
return {roundDiv(re, nn), roundDiv(im, nn)};
}
GI ggcd(GI x, GI y) { while (y.a || y.b) { GI r = x - gquot(x, y) * y; x = y; y = r; } return x; }
pair<ll, ll> twoSquares(ll p) { // prime p = 1 (mod 4) -> (a, b) with a^2 + b^2 = p
ll t = 0;
for (ll c = 2;; c++) if (power(c, (p - 1) / 2, p) == p - 1) { t = power(c, (p - 1) / 4, p); break; } // t^2 = -1
GI g = ggcd({p, 0}, {t, 1});
return {llabs(g.a), llabs(g.b)};
}Proof: Euclidean division, two squares, and r_2
Division. Write and round to the nearest ; then , so : norms halve each step, iterations, and the last non-zero remainder is a gcd (same argument as for integers). Two squares. With , but divides neither factor, so is not prime in : with . Some Gaussian prime factor of divides , so is not a unit, and it is not an associate of (since ); hence is a proper divisor of , so : with . A quadratic non-residue has , so squares to . : representations of as correspond to Gaussian integers of norm ; counting them through the factorization of into Gaussian primes gives (zero if some has odd exponent), which equals because is multiplicative. Checked:
twoSquaresfor every prime below , and against brute force for .