// 返回 gcd(a, b) ax + by = gcd(a, b) i64 exgcd(i64 a, i64 b, i64 &x, i64 &y){ if (b == 0) { x = 1; y = 0; return a; } i64 g = exgcd(b, a % b, y, x); y -= a / b * x; return g; }
// ax + b = 0 (mod m) 返回最小正整数解,通解的乘数 std::pair<i64, i64> sol(i64 a, i64 b, i64 m){ assert(m > 0); b *= -1; b = (b % m + m) % m; i64 x, y; i64 g = exgcd(a, m, x, y); if (g < 0) { g *= -1; x *= -1; y *= -1; } if (b % g != 0) { return {-1, -1}; } x = x * (b / g) % (m / g); if (x < 0) { x += m / g; } return {x, m / g}; }
std::array<i64, 3> exgcd(i64 a, i64 b){ if (!b) { return {a, 1, 0}; } auto [g, x, y] = exgcd(b, a % b); return {g, y, x - a / b * y}; }
// 找 ax + by = n 的正整数解 x, y boolfind_xy(i64 a, i64 b, i64 n, i64 &x, i64 &y){ i64 g = exgcd(a, b, x, y); // ax + by = gcd if (n % g != 0) { returnfalse; } i64 k = n / g; x *= k; y *= k; i64 dx = b / g; i64 dy = a / g; // 通解形式为 x = x + dx * t, y = y - dy * t i64 tmin = (x < 0) ? (-x + dx - 1) / dx : 0; i64 tmax = (y < 0) ? (-1) : (y / dy); if (tmin > tmax) { returnfalse; } x += dx * tmin; y -= dy * tmin; returntrue; }
线性求逆元
1 2 3 4 5 6 7 8
std::vector<int> inv(n + 1); inv[1] = 1; for (int i = 2; i <= n; i++) { inv[i] = 1ll * (p - p / i) * inv[p % i] % p; } for (int i = 1; i <= n; i++) { std::cout << inv[i] << "\n"; }
// 返回 gcd(a, b) ax + by = gcd(a, b) __int128 exgcd(__int128 a, __int128 b, __int128 &x, __int128 &y){ if (b == 0) { x = 1; y = 0; return a; } auto g = exgcd(b, a % b, y, x); y -= a / b * x; return g; }
__int128 crt(int n, std::vector<i64> &a, std::vector<i64> &b){ __int128 M = 1, ans = 0; for (int i = 1; i <= n; i++) { M = M * b[i]; } for (int i = 1; i <= n; i++) { __int128 m = M / b[i]; __int128 x, y; exgcd(m, b[i], x, y); ans = (ans + a[i] * m * x) % M; } ans = (ans % M + M) % M; return ans; };
分解质因数
记住循环最后还有一个 \(n\)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
int x; std::cin >> x;
for (int i = 2; i * i <= x; i++) { if (x % i == 0) { while (x % i == 0) { std::cout << i << "*"; x /= i; } } } if (x != 1) { std::cout << x << "\n"; }
求所有因数
1 2 3 4 5 6 7 8 9 10 11 12 13
std::vector<int> get_divisors(int n){ std::vector<int> res; for (int i = 1; i * i <= n; i++) { if (n % i == 0) { res.push_back(i); if (i != n / i) { res.push_back(n / i); } } } std::sort(res.begin(), res.end()); return res; }
// 求解单个数的欧拉函数 intphi(int n){ int res = n; for (int i = 2; i * i <= n; i++) { if(n % i == 0) { while(n % i == 0) { n /= i; } res = res / i * (i - 1); } } if(n > 1) { res = res / n * (n - 1); } return res; }
// 求解全部数的欧拉函数 constexprint N = 1e7; constexprint P = 1000003;
bool isprime[N + 1]; int phi[N + 1]; std::vector<int> primes;
std::fill(isprime + 2, isprime + N + 1, true); phi[1] = 1; for (int i = 2; i <= N; i++) { if (isprime[i]) { primes.push_back(i); phi[i] = i - 1; } for (auto p : primes) { if (i * p > N) { break; } isprime[i * p] = false; if (i % p == 0) { phi[i * p] = phi[i] * p; break; } phi[i * p] = phi[i] * (p - 1); } }
using i64 = longlong; using u64 = unsignedlonglong; using u32 = unsigned; using u128 = unsigned __int128;
// 求解单个数的欧拉函数 intphi(int n){ int res = n; for (int i = 2; i * i <= n; i++) { if (n % i == 0) { while (n % i == 0) { n /= i; } res = res / i * (i - 1); } } if (n > 1) { res = res / n * (n - 1); } return res; }
i64 qpow(i64 a, i64 b, i64 mod){ i64 res = 1; while (b) { if (b & 1) { res = res * a % mod; } a = a * a % mod; b /= 2; } return res; }
// 例:求 \sum_{i=1}^n k \pmod i = nk - \sum_{i=1}^n i(k/i) i64 ans = 1ll * n * k; for (int l = 1, r; l <= n; l = r + 1) { int q = k / l; if (q == 0) { r = n; } else { r = std::min(k / q, n); } ans -= 1ll * (l + r) * (r - l + 1) / 2 * q; }
// 向上取整的数论分块 for (int l = 1, r; l <= n; l = r + 1) { int k = (m + l - 1) / l; r = (k == 1) ? n : (m - 1) / (k - 1); // 区间 [l, r] \in [1, n] 内,所有 ceil(m / i) 的值都等于 k ans = std::min(ans, (k - 1) * l + n - m); }
voidsieve(int n){ minp.assign(n + 1, 0); phi.assign(n + 1, 0); sphi.assign(n + 1, 0); mu.assign(n + 1, 0); primes.clear(); phi[1] = 1; mu[1] = 1; for (int i = 2; i <= n; i++) { if (minp[i] == 0) { minp[i] = i; phi[i] = i - 1; mu[i] = -1; primes.push_back(i); } for (auto p : primes) { if (i * p > n) { break; } minp[i * p] = p; if (p == minp[i]) { phi[i * p] = phi[i] * p; break; } phi[i * p] = phi[i] * (p - 1); mu[i * p] = -mu[i]; } } for (int i = 1; i <= n; i++) { sphi[i] = sphi[i - 1] + phi[i]; mu[i] += mu[i - 1]; } }
// 快速求 \sum_{i=1}^n \mu(i) 的杜教筛 Z sumMu(int n){ if (n <= N) { return mu[n]; } if (fMu.count(n)) { return fMu[n]; } if (n == 0) { return0; } Z ans = 1; for (int l = 2, r; l <= n; l = r + 1) { r = n / (n / l); ans -= (r - l + 1) * sumMu(n / l); } fMu[n] = ans; return ans; }
i64 mul(i64 a, i64 b, i64 m){ returnstatic_cast<__int128>(a) * b % m; } i64 power(i64 a, i64 b, i64 m){ i64 res = 1 % m; for (; b; b >>= 1, a = mul(a, a, m)) if (b & 1) res = mul(res, a, m); return res; } boolisprime(i64 n){ if (n < 2) returnfalse; staticconstexprint A[] = {2, 3, 5, 7, 11, 13, 17, 19, 23}; int s = __builtin_ctzll(n - 1); i64 d = (n - 1) >> s; for (auto a : A) { if (a == n) returntrue; i64 x = power(a, d, n); if (x == 1 || x == n - 1) continue; bool ok = false; for (int i = 0; i < s - 1; ++i) { x = mul(x, x, n); if (x == n - 1) { ok = true; break; } } if (!ok) returnfalse; } returntrue; } std::vector<i64> factorize(i64 n){ std::vector<i64> p; std::function<void(i64)> f = [&](i64 n) { if (n <= 10000) { for (int i = 2; i * i <= n; ++i) for (; n % i == 0; n /= i) p.push_back(i); if (n > 1) p.push_back(n); return; } if (isprime(n)) { p.push_back(n); return; } auto g = [&](i64 x) { return (mul(x, x, n) + 1) % n; }; i64 x0 = 2; while (true) { i64 x = x0; i64 y = x0; i64 d = 1; i64 power = 1, lam = 0; i64 v = 1; while (d == 1) { y = g(y); ++lam; v = mul(v, std::abs(x - y), n); if (lam % 127 == 0) { d = std::gcd(v, n); v = 1; } if (power == lam) { x = y; power *= 2; lam = 0; d = std::gcd(v, n); v = 1; } } if (d != n) { f(d); f(n / d); return; } ++x0; } }; f(n); std::sort(p.begin(), p.end()); return p; }
for (int i = 2; i <= n; i++) { if (minp[i] == 0) { minp[i] = i; primes.push_back(i); factors[i] = {1, 1, i}; } for (auto p : primes) { if (1LL * i * p > n) { break; } minp[i * p] = p; auto tmp = factors[i]; tmp[0] *= p; sort(tmp.begin(), tmp.end()); factors[i * p] = tmp; if (p == minp[i]) { break; } } } }
voidpre(){ table.assign(V + 1, vector<int>(V + 1)); for (int i = 0; i <= V; i++) { table[i][0] = table[0][i] = i; } for (int i = 1; i <= V; i++) { for (int j = 1; j <= i; j++) { table[i][j] = table[j][i] = table[i % j][j]; } } }
intoperator()(int a, int b)const{ int g = 1; for (int i = 0; i < 3; i++) { int p = factors[a][i]; if (p == 1) { continue; } int tmp; if (p > V) { tmp = (b % p == 0 ? p : 1); } else { tmp = table[p][b % p]; } b /= tmp; g *= tmp; } return g; } };
constexprint inf = 3e18; intbsgs(int a, int b, int m, int k = 1){ static map<int, int> mp; mp.clear(); int cur = 1, t = sqrt(m) + 1; for (int B = 1; B <= t; B++) { cur = cur * a % m; mp[b * cur % m] = B; } int now = cur * k % m; for (int A = 1; A <= t; A++) { auto it = mp.find(now); if (it != mp.end()) { return A * t - it->second; } now = now * cur % m; } return -inf; }
intexbsgs(int a, int b, int m, int k = 1){ int A = a % m, B = b % m, M = m; if (b == 1) { return0; } int cur = 1 % m; for (int i = 0;; i++) { if (cur == B) { return i; } cur = cur * A % M; int d = gcd(a, m); if (b % d) { return -inf; } if (d == 1) { returnbsgs(a, b, m, k * a % m) + i + 1; } k = k * a / d % m; b /= d; m /= d; } }
using i64 = longlong; using u64 = unsignedlonglong; using u32 = unsigned;
using u128 = unsigned __int128; using i128 = __int128; using ld = longdouble;
constexprint P = 1e9 + 7; template <classT> constexpr T power(T a, int b){ T res = 1; for (; b; b /= 2, a *= a) { if (b % 2) { res *= a; } } return res; }
template <classT> constexpr T power(T a, int b, int P){ T res = 1; for (; b; b /= 2, a = a * a % P) { if (b % 2) { res = res * a % P; } } return res; }
boolinvMatrix(vector<vector<int>> &a, int P){ int n = a.size(); for (int i = 0, r; i < n; i++) { r = i; for (int j = i + 1; j < n; j++) if (a[j][i] > a[r][i]) { r = j; } if (r != i) { swap(a[i], a[r]); } if (!a[i][i]) { returnfalse; }
int inv = power(a[i][i], P - 2, P); for (int j = 0; j < 2 * n; j++) { a[i][j] = (a[i][j] * inv % P); } for (int k = 0; k < n; k++) { if (k == i || a[k][i] == 0) { continue; } int f = a[k][i]; for (int j = i; j < n * 2; j++) { a[k][j] = (a[k][j] - f * a[i][j]) % P; if (a[k][j] < 0) { a[k][j] += P; } } } } returntrue; }
template <classT> constexpr T power(T a, int b){ T res = 1; for (; b; b /= 2, a *= a) { if (b % 2) { res *= a; } } return res; }
template <classT> constexpr T power(T a, int b, int P){ T res = 1; for (; b; b /= 2, a = a * a % P) { if (b % 2) { res = res * a % P; } } return res; }
// -1:无解 0:无穷多解 1:唯一解 // 注意读入矩阵时要给系数取模 pair<vector<int>, int> gauss(vector<vector<int>> &a, int P) { int n = a.size(); vector<int> ans(n, -1); int r = 0; for (int c = 0; c < n; c++) { for (int i = r + 1; i < n; i++) { if (a[i][c] > a[r][c]) { swap(a[r], a[i]); } } if (a[r][c] == 0) { continue; } int inv = power(a[r][c], P - 2, P); inv = (inv % P + P) % P; for (int i = n; i >= c; i--) { a[r][i] *= inv; a[r][i] %= P; } for (int i = r + 1; i < n; i++) { for (int j = n; j >= c; j--) { a[i][j] -= a[i][c] * a[r][j] % P; a[i][j] = (a[i][j] % P + P) % P; } } r++; } if (r < n) { for (int i = r; i < n; i++) { if (a[i][n]) { return {ans, -1}; } } return {ans, 0}; } for (int j = n - 1; j > 0; j--) { for (int i = 0; i < j; i++) { a[i][n] -= a[j][n] * a[i][j] % P; a[i][n] = (a[i][n] % P + P) % P; a[i][j] -= a[j][j] * a[i][j] % P; a[i][j] = (a[i][j] % P + P) % P; } } for (int i = 0; i < n; i++) { ans[i] = a[i][n]; } return {ans, 1}; }
// get xor rank intgauss(vector<vector<int>> &ori){ int n = ori.size(); int m = ori[0].size(); vector<bitset<N>> a(n); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (ori[i][j] == 1) { a[i][j] = 1; } } } int r = 0; for (int c = 0; c < m && r < n; c++) { int p = r; while (p < n && !a[p][c]) { p++; } if (p == n) { continue; } swap(a[r], a[p]); for (int i = r + 1; i < n; i++) { if (a[i][c]) { a[i] ^= a[r]; } } r++; } return n - r; }
using i64 = longlong; using u64 = unsignedlonglong; using u32 = unsigned;
using u128 = unsigned __int128; using i128 = __int128; using ld = longdouble;
constdouble PI = acos(-1.0);
structComplex { double x, y; Complex(double x_ = 0, double y_ = 0) { x = x_; y = y_; } Complex operator+(const Complex &b) const { returnComplex(x + b.x, y + b.y); } Complex operator-(const Complex &b) const { returnComplex(x - b.x, y - b.y); } Complex operator*(const Complex &b) const { returnComplex(x * b.x - y * b.y, x * b.y + y * b.x); } };
voidchange(Complex y[], int len){ for (int i = 1, j = len / 2, k; i < len - 1; i++) { if (i < j) { std::swap(y[i], y[j]); } k = len / 2; while (j >= k) { j -= k; k /= 2; } if (j < k) { j += k; } } }
voidfft(Complex y[], int len, int on){ change(y, len); for (int h = 2; h <= len; h *= 2) { Complex wn(cos(2 * PI / h), sin(on * 2 * PI / h)); for (int j = 0; j < len; j += h) { Complex w(1, 0); for (int k = j; k < j + h / 2; k++) { Complex u = y[k]; Complex t = w * y[k + h / 2]; y[k] = u + t; y[k + h / 2] = u - t; w = w * wn; } } } if (on == -1) { for (int i = 0; i < len; i++) { y[i].x /= len; } } }
// 注意数组要开到 2^x > n + m constexprint N = 2100010; Complex a[N], b[N], ans[N];
int n, m; cin >> n >> m; for (int i = 0; i <= n; i++) { cin >> a[i].x; } for (int i = 0; i <= m; i++) { cin >> b[i].x; } int len = 1; while (len <= n + m) { len *= 2; } fft(a, len, 1); fft(b, len, 1); for (int i = 0; i < len; i++) { ans[i] = a[i] * b[i]; } fft(ans, len, -1); for (int i = 0; i <= n + m; i++) { cout << (int)(ans[i].x + 0.5) << " \n"[i == n + m]; }
i64 power(i64 a, i64 e, i64 mod){ i64 r = 1 % mod; a %= mod; while (e) { if (e & 1) r = (i128)r * a % mod; a = (i128)a * a % mod; e >>= 1; } return r; }
voidbit_reverse(vector<i64> &a){ int n = (int)a.size(); int j = 0; for (int i = 1; i < n; ++i) { int bit = n >> 1; for (; j & bit; bit >>= 1) j ^= bit; j ^= bit; if (i < j) swap(a[i], a[j]); } }
voidntt(vector<i64> &a, int sign, i64 mod){ int n = (int)a.size(); bit_reverse(a); for (int len = 2; len <= n; len <<= 1) { i64 wn = power(G, (mod - 1) / len, mod); if (sign == -1) wn = power(wn, mod - 2, mod); for (int i = 0; i < n; i += len) { i64 w = 1; int half = len >> 1; for (int j = 0; j < half; ++j) { i64 u = a[i + j]; i64 v = (i128)w * a[i + j + half] % mod; a[i + j] = u + v; if (a[i + j] >= mod) a[i + j] -= mod; a[i + j + half] = u - v; if (a[i + j + half] < 0) a[i + j + half] += mod; w = (i128)w * wn % mod; } } } if (sign == -1) { i64 inv = power(n, mod - 2, mod); for (int i = 0; i < n; ++i) a[i] = (i128)a[i] * inv % mod; } }
vector<i64> multiply_mod(vector<i64> a, vector<i64> b, i64 mod){ if (a.empty() || b.empty()) return {}; int tot = (int)a.size() + (int)b.size() - 1; int sz = 1; while (sz < tot) sz <<= 1; a.resize(sz); b.resize(sz); ntt(a, 1, mod); ntt(b, 1, mod); for (int i = 0; i < sz; ++i) a[i] = (i128)a[i] * b[i] % mod; ntt(a, -1, mod); a.resize(tot); return a; }
vector<i64> multiply_crt(vector<i64> a, vector<i64> b, i64 p){ if (a.empty() || b.empty()) return {}; auto c1 = multiply_mod(a, b, mod1); auto c2 = multiply_mod(a, b, mod2); auto c3 = multiply_mod(a, b, mod3); int n = (int)c1.size();
intmain(){ ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; longlong p; if (!(cin >> n >> m >> p)) return0; vector<i64> A(n + 1), B(m + 1); for (int i = 0; i <= n; ++i) cin >> A[i]; for (int i = 0; i <= m; ++i) cin >> B[i];
auto C = multiply_crt(A, B, p); for (int i = 0; i <= n + m; ++i) { cout << C[i] << (i == n + m ? '\n' : ' '); } return0; }