数学
组合数
ll inv[N],inc[N]; void init(){ inc[0]=1; for(int i=1;i<=N;i++){ inc[i]=inc[i-1]*i % mod; } inv[0]=1; for(int i=1;i<=N;i++){ inv[i]=powmod(inc[i],mod-2); } } ll C(int a,int b){ if(a<b) return 0; return inc[a]*inv[a-b]%mod*inv[b]%mod; } ll Catalan(int n,int m){ return (C(n + m,n) - C(n + m,m - 1) + mod) % mod; }
矩阵
template<class T, const int SZ> struct Matrix { typedef Matrix Mat; array<array<T, SZ>, SZ> d{}; Mat operator*(const Mat& mat) const { Mat a; for (int i = 0; i < SZ; i++) { for (int j = 0; j < SZ; j++) { for (int k = 0; k < SZ; k++) { a.d[i][j] += d[i][k]*mat.d[k][j]; } } } return a; } vector<T> operator*(const vector<T>& vec) const { vector<T> ret(SZ); for (int i = 0; i < SZ; i++) { for (int j = 0; j < SZ; j++) { ret[i] += d[i][j] * vec[j]; } } return ret; } Mat operator^(ll p) const { assert(p >= 0); Mat a, b(*this); for (int i = 0; i < SZ; i++) a.d[i][i] = 1; while (p) { if (p&1) a = a * b; b = b * b; p >>= 1; } return a; } };
扩展欧几里得
int exgcd(int a, int b, int &x, int &y){ if (b == 0) { x=1, y=0; return a; } int xx, yy; int d = exgcd(b, a%b, xx, yy); x = yy; y = xx - (a / b) * yy; return d; } int calc(int a, int b) { int x, y; int d = exgcd(a, b, x, y); b /= d; if(b < 0) b = -b; int cnt = x % b; if (cnt < 0) cnt += b; return cnt; }
乘法逆元
long long inv[N]; void Inv(){ inv[1]=1; int ans=1; for(int i=2;i<=N;i++){ inv[i]=(mod-mod/i)*inv[mod%i]%mod; } }
线性筛
constexpr int N=50000000; int pr[N/5], p[N+100], tot; int n; void prime(){ p[1] = 1; for(int i = 2; i <= N; i++){ if(!p[i]) p[i]=i, pr[++tot] = i; for(int j=1; j <= tot && i * pr[j] <= N; j++){ p[i * pr[j]] = pr[j]; if(pr[j] == p[i]) break; } } }
解同余方程组
ll exgcd(ll a, ll b, ll &x, ll &y) { if(b == 0){ x = 1; y = 0; return a; } ll d = exgcd(b, a%b, y, x); y -= (a / b) * x; return d; } void merge(ll &a, ll &b, ll c, ll d) { if (a == -1 && b == -1) return; ll x, y; ll g = exgcd(b, d, x, y); if ((c - a) % g != 0) { a = b = -1; } d /= g; ll t0 = ((c - a) / g) % d * x % d; while (t0 < 0) t0 += d; a = b * t0 + a; b = b * d; } void solve() { ll a = 0, b = 1; //x mod b=a int n; cin >> n; for (int i = 1; i <= n; i++) { ll c, d; cin >> c >> d; merge(a, b, d, c); } cout << a << endl; }
积性函数
#include <bits/stdc++.h> using namespace std; constexpr int N=20100000; int pr[N/5], p[N], pe[N], tot; int n, ans, f[N]; void compute(int n, function<void(int)> calcpe) { f[1] = 1; for (int i = 2; i <= n; i++) { if (i == pe[i]) calcpe(i); else f[i] = f[pe[i]] * f[i / pe[i]]; } } int main() { cin >> n; p[1] = 1; for(int i = 2; i <= n; i++){ if(!p[i]) p[i] = i, pe[i] = i, pr[++tot] = i; for(int j=1; j <= tot && i * pr[j] <= n; j++){ p[i * pr[j]] = pr[j]; if(pr[j] == p[i]) { pe[i * pr[j]] = pe[i] * pr[j]; break; } else { pe[i * pr[j]] = pr[j]; } } } compute(n, [&](int x){ f[x] = f[x / p[x]] + 1; });//D(i) compute(n, [&](int x){ f[x] = f[x / p[x]] + x; });//Sigma(i) compute(n, [&](int x){ f[x] = x / p[x] * (p[x] - 1); });//Phi(i) compute(n, [&](int x){ f[x] = ((f[x] == x) ? -1 : 0); });//Mu(i) return 0; }
阶
#include <bits/stdc++.h> using namespace std; using ll = long long; constexpr int N = 200010; ll powmod(ll a,ll b,ll mod) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} int pf[N]; int main() { ios::sync_with_stdio(0); cin.tie(0); cin.exceptions(cin.failbit); int p, t; cin >> p >> t; int m = p - 1; int k = 0; for (int i = 2; i * i <= m; i++) { if (m % i == 0) { pf[k++] = i; while(m % i == 0) m /= i; } } if (m != 1) pf[k++] = m; while (t--) { int a; cin >> a; int d = p - 1; for (int i = 0; i < k; i++) { while ((d % pf[i] == 0) && powmod(a, d / pf[i], p) == 1) d /= pf[i]; } cout << d << "\n"; } return 0; }
原根
#include <bits/stdc++.h> using namespace std; using ll = long long; constexpr int N = 200010; ll powmod(ll a,ll b,ll mod) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} int pf[N]; int main() { ios::sync_with_stdio(0); cin.tie(0); cin.exceptions(cin.failbit); int t; cin >> t; while (t--) { int p; cin >> p; int m = p - 1, k = 0; for (int i = 2; i * i <= m; i++) { if (m % i == 0) { pf[k++] = i; while(m % i == 0) m /= i; } } if (m != 1) pf[k++] = m; int d = p - 1; for (int g = 1; g < p; g++){ bool vaild = true; for (int i = 0; i < k; i++) { if (powmod(g, d / pf[i], p) == 1) vaild = false; } if (vaild) { cout << g << "\n"; break; } } } return 0; }
指数方程
#include <bits/stdc++.h> using namespace std; using ll = long long; constexpr int N = 200010; ll powmod(ll a,ll b,ll mod) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} int a, b, m; void solve() { cin >> a >> b >> m; int T = sqrt(m) + 2; unordered_map<int, int> hs; ll v = powmod(a, T, m), d = 1; for (int q = 1; q <= T; q++) { d = d * v % m; if (!hs.count(d)) hs[d] = q * T; } int ans = m + 1; d = b; for (int r = 1; r <= T; r++) { d = d * a % m; if (hs.count(d)) ans = min(ans, hs[d] - r); } if (ans >= m) { cout << "-1\n"; } else { cout << ans << "\n"; } } int main() { ios::sync_with_stdio(0); cin.tie(0); cin.exceptions(cin.failbit); int t; cin >> t; while (t--) { solve(); } return 0; }
莫比乌斯反演
#include <bits/stdc++.h> using namespace std; constexpr int N=20100000; int pr[N/5], p[N], pe[N], tot; int n, ans, f[N], mu[N], g[N]; int main() { cin >> n; p[1] = 1, mu[1] = 1; for(int i = 2; i <= n; i++){ if(!p[i]) p[i] = i, mu[i] = -1, pr[++tot] = i; for(int j=1; j <= tot && i * pr[j] <= n; j++){ p[i * pr[j]] = pr[j]; if(pr[j] == p[i]) { pe[i * pr[j]] = 0; break; } else { pe[i * pr[j]] = -mu[i]; } } } //g = f * mu; //g[n] = sum_{d|n} f[d] * mu[n / d] //g[n] = sum_{n = d1 * d2} f[d1] * mu[d2] for (int d1 = 1; d1 <= n; d1++) { for (int d2 = 1; d1 * d2 <= n; d2++) { g[d1 * d2] += f[d1] * mu[d2]; } } return 0; }

浙公网安备 33010602011771号