LL gcd(LL a, LL b){ return b == 0 ? a : gcd(b, a % b); }
lcm(a, b) = a / gcd(a, b) * b
扩展欧几里得算法(exGCD)
目标: 寻找一对整数(x,y),使ax+by=gcd(a,b)
1 2 3 4
voidexgcd(LL a, LL b, LL& d, LL& x, LL& y){ if (!b) { d = a; x = 1; y = 0; } //d为gcd(a, b) else { exgcd(b, a % b, d, y, x); y -= x * (a / b); } }
裴蜀定理
ax+by=c且x,y全为正整数,则当且仅当gcd(a,b)|c
素数相关
Eratosthenes筛法
1 2 3 4 5 6 7 8 9 10 11
bool vis[maxn]; int prime[maxn]; voidgetprime(int n){ int m = (int)sqrt(n + 0.5), num = 0; memset(vis, 0, sizeof(vis)); vis[0] = vis[1] = 1; for (int i = 2; i <= m; ++i) if (!vis[i]) { prime[++num] = i; for (int j = i * i; j <= n; j += i) vis[j] = 1; } }
欧拉线性筛
1 2 3 4 5 6 7 8 9 10 11 12 13
voidgetprime(int n){ vis[1] = true; for (int i = 2; i <= n; i++) { if (!vis[i]) { prime[++cnt] = i; } for (int j = 1; j <= cnt; j++) { int v = i * prime[j]; if (v > n) break; vis[v] = true; } } }
LL Random(LL n){ return (LL)((double)rand() / RAND_MAX * n + 0.5); } boolWitness(LL a, LL n){ LL m = n - 1; int j = 0; while (!(m & 1)) { j++; m >>= 1; } LL x = pow_mod(a, m, n); if (x == 1 || x == n - 1) returnfalse; while (j--) { x = x * x % n; if (x == n - 1) returnfalse; } returntrue; } boolMiller_Rabin(LL n){ if (n < 2) returnfalse; if (n == 2) returntrue; if (!(n & 1)) returnfalse; for (int i = 1; i <= 30; ++i) { LL a = Random(n - 2) + 1; if (Witness(a, n)) returnfalse; } returntrue; }
LL mul_mod(LL a, LL b, LL n){ LL res = 0; while (b > 0) { if (b & 1) res = (res + a) % n; a = (a + a) % n; b >>= 1; } return res; }
快速幂 apmodn
1 2 3 4 5 6 7
LL pow_mod(LL a, LL p, LL n){ if (p == 0 && n == 1) return0; if (p == 0) return1; LL ans = pow_mod(a, p / 2, n); ans = ans * ans % n; if (p % 2 == 1) ans = ans * a % n; return ans; }
使用位运算:
1 2 3 4 5
LL pow_mod(LL a, LL p, LL n){ a %= n; LL ans = 1; for (; p; p >>= 1, a *= a, a %= n) if(p & 1) ans = ans * a % n; return ans; }
欧拉φ函数
φ(n)=n(1−1p1)(1−1p2)…(1−1pk) φ(n)表示不超过n且与n互质的整数个数
求值
1 2 3 4 5 6 7 8 9
inteuler_phi(int n){ int m = (int)sqrt(n + 0.5); int ans = n; for (int i = 2; i <= m; ++i) if (n % i == 0) { ans = ans / i * (i - 1); while (n % i == 0) n /= i; } if (n > 1) ans = ans / n * (n - 1); return ans; }
筛欧拉函数表
1 2 3 4 5 6 7 8 9
int phi[maxn]; voidphi_table(int n){ for (int i = 2; i <= n; ++i) phi[i] = 0; phi[1] = 1; for (int i = 2; i <= n; ++i) if (!phi[i]) for (int j = i; j <= n; j += i) { if (!phi[j]) phi[j] = j; phi[j] = phi[j] / i * (i - 1); } }
同余式定理
欧拉定理
若gcd(a,n)=1,则aφ(n)≡1(modn)
费马小定理
若p为质数,则ap−1≡1(modp)
威尔逊定理
若p为质数,则(p−1)!≡−1(modp)
乘法逆元
a÷bmodn=a×b−1modn b−1称为b在模n意义下的逆元
n为质数
使用费马小定理, a−1=an−2
n不为质数
递归求解
1 2 3 4 5
LL inv(LL a, LL n){ LL d, x, y; exgcd(a, n, d, x, y); return d == 1 ? (x + n) % n : -1; }
筛逆元表
1 2 3 4 5 6 7
int inv_table[maxn]; voidgetinv(int n, int p){ inv_table[1] = 1; for (int i = 2; i <= n; ++i) { inv_table[i] = (LL)(p - p / i) * inv_table[p % i] % p; } }
同余方程
ax≡b(modn)可以化为ax+ny=b使用扩展欧拉定理解决
中国剩余定理(China Remainder Theorem)
求解x≡ai(modmi)满足mi两两互质
1 2 3 4 5 6 7 8 9 10
LL crt(int n, int* a, int* m){ LL M = 1, d, y, x = 0; for (int i = 0; i < n; ++i) M *= m[i]; for (int i = 0; i < n; ++i) { LL w = M / m[i]; exgcd(m[i], w, d, d, y); x = (x + y * w * a[i]) % M; } return (x + M) % M; }
扩展中国剩余定理(exCRT)
mi不一定两两互质
1 2 3 4 5 6 7 8 9 10 11 12 13
LL excrt(LL n, LL* a, LL* m){ LL x, y, k, M = m[0], ans = a[0]; for (int i = 1; i < n; ++i) { LL A = M, B = m[i], C = (a[i] - ans % B + B) % B, gcd; exgcd(A, B, gcd, x, y); LL bg = B / gcd; if (C % gcd != 0) return-1; x = mul_mod(x, C / gcd, bg); ans += x * M; M *= bg; ans = (ans % M + M) % M; } return (ans % M + M) % M; }
离散对数(BSGS)
求解ax≡b(modn)满足n为质数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
intlog_mod(int a, int b, int n){ int m, v, e = 1, i; m = (int)sqrt(n + 0.5); v = inv(pow_mod(a, m, n), n); map<int, int> x; x[1] = 0; for (i = 1; i < m; ++i) { e = mul_mod(e, a, n); if (!x.count(e)) x[e] = i; } for (i = 0; i < m; ++i) { if (x.count(b)) return i * m + x[b]; b = mul_mod(b, v, n); } return-1; }