1 最大公约数 (gcd)
int gcd(int a, int b) {return b ? gcd(b, a % b) : a;}
2 快速幂 (递归版本)
ll PowerMod(ll a, ll n, ll m = mod) { if (!n || a == 1) return 1ll; ll s = PowerMod(a, n >> 1, m); s = s * s % m; return n & 1 ? s * a % m : s; }
3 快速幂 (非递归版本)
ll PowerMod(ll a, int n, ll c = 1) { for (; n; n >>= 1, a = a * a % mod) if (n & 1) c = c * a % mod; return c; }
4 扩展 Euclid 算法 (exgcd)
ll exgcd(ll a, ll b, ll &x, ll &y) { if (b) { ll d = exgcd(b, a % b, y, x); return y -= a / b * x, d; } else return x = 1, y = 0, a; }
5 基本预处理
// factorials, fact-inverses, unbounded void init() { int i; for (*fact = i = 1; i < N; ++i) fact[i] = (ll)fact[i - 1] * i % mod; --i; finv[i] = PowerMod(fact[i], mod - 2); for (; i; --i) finv[i - 1] = (ll)finv[i] * i % mod; } // factorials, fact-inverses, bounded void init(int n) { int i; for (*fact = i = 1; i <= n; ++i) fact[i] = (ll)fact[i - 1] * i % mod; finv[n] = PowerMod(fact[n], mod - 2); for (i = n; i; --i) finv[i - 1] = (ll)finv[i] * i % mod; } // inverses, factorials, fact-inverses, unbounded void init() { int i; for (inv[1] = 1, i = 2; i < N; ++i) inv[i] = ll(mod - mod / i) * inv[mod % i] % mod; for (*finv = *fact = i = 1; i < N; ++i) fact[i] = (ll)fact[i - 1] * i % mod, finv[i] = (ll)finv[i - 1] * inv[i] % mod; } // inverses, factorials, fact-inverses, bounded void init(int n) { int i; for (inv[1] = 1, i = 2; i <= n; ++i) inv[i] = ll(mod - mod / i) * inv[mod % i] % mod; for (*finv = *fact = i = 1; i <= n; ++i) fact[i] = (ll)fact[i - 1] * i % mod, finv[i] = (ll)finv[i - 1] * inv[i] % mod; }
6 线性筛素数 (筛最小素因子)
int pn = 0, c[N], p[78540]; void sieve(int n) { int i, j, v; memset(c, -1, sizeof c); for (i = 2; i <= n; ++i) { if (!~c[i]) p[pn] = i, c[i] = pn++; for (j = 0; (v = i * p[j]) <= n && j <= c[i]; ++j) c[v] = j; } }
7 Miller-Rabin 素数测试
// No pseudoprime below 2^64 to base 2, 3, 5, 7, 11, 13, 82, 373. const int test[8] = {2, 3, 5, 7, 11, 13, 82, 373}; bool Miller_Rabin(ll n) { if (n < MAX) return !c[n] && n > 1; int c, i, j; ll s = n - 1, u, v; for (c = 0; !(s & 1); ++c, s >>= 1); for (i = 0; i < 8; ++i) { if (!(n % test[i])) return false; u = PowerMod(test[i], s, n); for (j = 0; j < c; ++j, u = v) if (v = MulMod(u, u, n), u != 1 && u != n - 1 && v == 1) return false; if (u != 1) return false; } return true; }
8 分解质因数
// version 1 inline void push(ll prime, int alpha) {pr[cnt] = prime, al[cnt++] = alpha;} // version 2 inline void push(ll prime, int alpha) { map::iterator it = result.find(prime); it == result.end() ? (void)result.emplace(prime, alpha) : (void)(it->second += alpha); } void factor(ll n) { int i, j; cnt = 0; // result.clear(); for (i = 0; n > 1; ) { if (n >= N) { for (; (ll)p[i] * p[i] <= n && n % p[i]; ++i); if (n % p[i]) return push(n, 1); } else i = c[n]; for (j = 0; !(n % p[i]); n /= p[i], ++j); push(p[i], j); } }
9 线性筛 Euler φ 函数
void sieve(int n) { int i, j, v; phi[1] = 1; memset(c, -1, sizeof c); for (i = 2; i <= n; ++i) { if (!~c[i]) p[pn] = i, c[i] = pn++, phi[i] = i - 1; for (j = 0; (v = i * p[j]) <= n && j < c[i]; ++j) c[v] = j, phi[v] = phi[i] * (p[j] - 1); if (v <= n) c[v] = j, phi[v] = phi[i] * p[j]; } }
10 线性筛 Möbius μ 函数
void sieve(int n) { int i, j, v; mu[1] = 1; memset(c, -1, sizeof c); for (i = 2; i <= n; ++i) { if (!~c[i]) p[pn] = i, c[i] = pn++, mu[i] = -1; for (j = 0; (v = i * p[j]) <= n && j < c[i]; ++j) c[v] = j, mu[v] = -mu[i]; if (v <= n) c[v] = j; } }
11 遍历 ⌊n / i⌋ 的所有可能值 (旧版整除分块)
#define next(n, i) (n / (n / i + 1)) for(i = n; i >= 1; i = j){ j = next(n, i); // do something } #define _next(n, i) (n / (n / (i + 1))) for(i = 0; i < n; i = j){ j = _next(n, i); // do something } // 0 1 100 1 2 50 2 3 33 3 4 25 4 5 20 5 6 16 16 6 7 14 7 8 12 8 9 11 9 10 10 10 11 9 11 12 8 12 13 7 14 15 6 16 17 5 20 21 4 25 26 3 33 34 2 50 51 1 100 101 0 ?
12 新版整除分块
// int32 ver. int n, cnt, srn; int v[G]; inline int ID(int x) {return x <= srn ? x : cnt + 1 - n / x;} { int i; srn = sqrt(n), cnt = srn * 2 - (srn * (srn + 1) > n); for (i = 1; i <= srn; ++i) v[i] = i, v[cnt - i + 1] = n / i; } // int64 ver. ll n, v[G]; int cnt, srn; inline int ID(ll x) {return x <= srn ? x : cnt + 1 - n / x;} { int i; srn = sqrt(n), cnt = srn * 2 - (srn * (srn + 1) > n); for (i = 1; i <= srn; ++i) v[i] = i, v[cnt - i + 1] = n / i; }
13 杜氏求和法 / 杜教筛
void Dsum() { int i, j, k, l, n, sq, _; for (i = 1; i <= cnt && v[i] < N; ++i) Mu[i] = smu[v[i]], Phi[i] = sphi[v[i]]; for (; i <= cnt; ++i) { int &m = Mu[i]; ll &p = Phi[i]; n = v[i], sq = sqrt(n), m = 1, p = n * (n + 1ll) / 2, l = n / (sq + 1); for (j = sq; j; --j) { _ = (k = n / j) - l, m -= _ * smu[j], p -= _ * sphi[j], l = k; if (j != 1 && k > sq) m -= Mu[_ = ID(k)], p -= Phi[_]; } } }
14大小步离散对数
int Boy_Step_Girl_Step(){ mii :: iterator it; ll boy = 1, girl = 1, i, t; for(i = 0; i < B; i++){ m.insert(pr((int)boy, i)); // if there exists in map, then ignore it (boy *= a) %= p; } for(i = 0; i * B < p; i++){ t = b * inv(girl) % p; it = m.find((int)t); if(it != m.end()) return i * B + it->second; (girl *= boy) %= p; } return -1; } // input p and then B = (int)sqrt(p - 1); // inv(x) is the multiplicative inverse of x in Z[p]. // mii: mapand m is a variable of which.
15 Pollard-Rho 素因数分解
ll Pollard_Rho(ll n, int c) { ll i = 1, k = 2, x = rand() % (n - 1) + 1, y = x, p; for (; k <= 131072; ) { x = (MulMod(x, x, n) + c) % n; p = gcd((ull)(y - x + n) % n, n); if (p != 1 && p != n) return p; if (++i == k) y = x, k <<= 1; } return 0; } inline void push(ll prime, int alpha) { map::iterator it = result.find(prime); it == result.end() ? (void)result.insert(pr(prime, alpha)) : (void)(it->second += alpha); } void factor(ll n) { int i, j, k; ll p; for (i = 0; n != 1; ) if (n >= MAX) { if (Miller_Rabin(n)) {push(n, 1); return;} for (k = 97; !(p = Pollard_Rho(n, k)); --k); factor(p); n /= p; } else { i = (c[n] ? c[n] : n); for (j = 0; !(n % i); n /= i, ++j); push(i, j); } }