// 不带模数的快速幂, 基本不用 intquick_pow(int base, int exponent){ int res = 1; while (exponent) { if (exponent & 1) res *= base; base *= base; exponent >>= 1; } return res; }
// 带模数的快速幂 intquick_pow(int base, int exponent, int modulo = MOD){ int res = 1 % modulo; base %= modulo; while (exponent) { if (exponent & 1) res = res * base % modulo; base = base * base % modulo; exponent >>= 1; } return res; }
// 用于解决 1e18 级别取模. 通常使用浮点乘更快 // 考虑效率 __int128_t 更快约 20% intfloat_mul(int x, int y, int modulo){ int d = (longdouble)x / modulo * y + 0.5; int r = x * y - d * modulo; if (r < 0) r += modulo; return r; }
// 矩阵快速幂. 复杂度: O(log(exponent)), 取模需写入 Matrix类中 classMatrix { public: vector<vector<int>> data; int n, m; Matrix() : n(0), m(0) {} Matrix(int n, int m) : data(vector<vector<int>>(n, vector<int>(m, 0))), n(n), m(m) {} Matrix(vector<vector<int>> vec) : data(vec), n(data.size()), m(data.front().size()) {} vector<int> &operator[](int idx) { return data[idx]; } Matrix operator*(Matrix &x) { if (n != x.m) throw"Matrix size error."; Matrix res(x.n, m); for (int i = 0; i < x.n; i++) for (int j = 0; j < m; j++) for (int k = 0; k < n; k++) res[i][j] = (res[i][j] + data[k][j] * x[i][k]) % MOD; return res; } Matrix operator*=(Matrix &x) { return *this = *this * x; } };
Matrix matrix_pow(Matrix base, int exponent){ Matrix res = base; exponent--; while (exponent) { if (exponent & 1) res *= base; base *= base; exponent >>= 1; } return res; }
// 快速幂. 复杂度: O(log(exponent)) intquick_pow(int base, int exponent){ int res = 1 % MOD; base %= MOD; while (exponent) { if (exponent & 1) res = res * base % MOD; base = base * base % MOD; exponent >>= 1; } return res; }
// 欧拉函数. 求区间 [1, x] 中与 x 互质的数的个数. 复杂度: O(logx) -> O(x^0.5). int _euler(int x) { if (x < 2) return0; int res = x; for (int i = 2; i <= x / i; i++) if (x % i == 0) { res = res / i * (i - 1); while (x % i == 0) x /= i; } if (x > 1) res = res / x * (x - 1); return res; } inlineinteuler(int x){ staticint old = -1, res = -1; if (x == old) return res; old = x, res = _euler(x); return res; }
// 扩展欧拉定理. 求 base ^ exponent = x (mod MOD). 复杂度: o(log(min(exponent, MOD))) // 用于处理 exponent 很大的幂数, 如 base ^ (a ^ b) = x (mod MOD) intexeuler(int base, int exponent){ if (__gcd(base, MOD) == 1) returnquick_pow(base, exponent % euler(MOD)); elseif (exponent < euler(MOD)) returnquick_pow(base, exponent); else returnquick_pow(base, exponent % euler(MOD) + euler(MOD)); }
int euler_modulo, gcd_base_modulo, size_block; int size_pow[SQR]; int base_pow[SQR];
// 欧拉函数. 复杂度: O(logx) -> O(sqrt(x)). inteuler(int x){ if (x < 2) return0; int res = x; for (int i = 2; i <= x / i; i++) if (x % i == 0) { res = res / i * (i - 1); while (x % i == 0) x /= i; } if (x > 1) res = res / x * (x - 1); return res; }
// 光速幂预处理. 基于分块, 时间复杂度: O(sqrt(euler(base))) voidload_supper_pow(int base){ base %= MOD; ::euler_modulo = euler(MOD); ::gcd_base_modulo = __gcd(base, MOD); ::size_block = sqrt(euler_modulo * 2); base_pow[0] = 1; for (int i = 1; i <= size_block; i++) base_pow[i] = base_pow[i - 1] * base % MOD; size_pow[0] = 1; for (int i = 1, lim = euler_modulo * 2 / size_block; i <= lim; i++) size_pow[i] = size_pow[i - 1] * base_pow[size_block] % MOD; }