boolis_prime(int x) { if (x < 2) returnfalse; for (int i = 2; i <= x / i; i ++ ) if (x % i == 0) returnfalse; returntrue; }
欧拉筛求质数
时间复杂度O(n)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
//p:存质数 cnt:质数的个数 st[i]:i是否为质数 int p[N], cnt; bool st[N];
voidget_primes(int n) { for (int i = 2; i <= n; i ++ ) { if (!st[i]) p[cnt ++ ] = i; for (int j = 0; p[j] <= n / i; j ++ ) { st[p[j] * i] = true; if (i % p[j] == 0) break; } } }
分解质因数
普通分解质因数
时间复杂度O(n^0.5^)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
//分解为算术基本定理的形式 voiddivi(int x) { for (int i = 2; i <= x / i; i ++ ) { if (x % i == 0) { int cnt = 0; while (x % i == 0) { x /= i; cnt ++ ; } // i质数 cnt质数的指数 printf("%d %d\n", i, cnt); } } if (x > 1) printf("%d 1\n", x); }
阶乘分解质因数
时间复杂度约为O(n)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
//分解为算术基本定理的形式 int p[N], cnt; bool st[N]; longlong n;
//return 算术基本定理分解n!底数p的指数 intget(int n, int p) { int res = 0; for (int i = n; i; i /= p) res += i / p; //核心:先加上n!中p¹的个数, 再加p²...... return res; }
for (int i = 0; i < cnt; i ++ ) { int ans = get(n, p[i]); if (ans) printf("%d %d\n", p[i], ans); }
最大公约数gcd
时间复杂度约为O(logn)
1 2 3 4
intgcd(int a, int b) { return !b ? a : gcd(b, a % b); }
试除法求约数
时间复杂度为O(n^0.5^)
1 2 3 4 5 6 7 8 9
vector<int> res; for (int i = 1; i <= x / i; i ++ ) { if (x % i == 0) { res.push_back(i); if (i != x / i) res.push_back(x / i); } }
for (int i = 2; i <= a / i; i ++ ) { while (a % i == 0) { a /= i; mp[i] ++ ; } } if (a > 1) mp[a] ++ ;
LL res = 1; for (auto t:mp) { LL tmp = 1; while (t.second -- ) tmp = tmp * t.first + 1; res = res * tmp % MOD; }
龟速乘
时间复杂度为O(logn)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
//实现64位整数乘法不溢出 //求a * b % p typedeflonglong LL; LL qmu(LL a, LL b, LL p) { LL res = 0; while (b) { if (b & 1) res = (res + a) % p; a = (a + a) % p; b >>= 1; } return res; }
快速幂
时间复杂度为O(logn)
1 2 3 4 5 6 7 8 9 10 11 12
typedeflonglong LL; LL qmi(LL a, LL b, LL p) { LL res = 1; while (b) { if (b & 1) res = res * a % p; b >>= 1; a = a * a % p; } return res; }
矩阵乘法
时间复杂度为O(n*m*k)
1 2 3 4 5 6 7 8 9 10
int t[N][N];
voidmul(int a[N][N], int b[N][N]) { memset(t, 0, sizeof t); for (int i = 1; i <= n; i ++ ) for (int j = 1; j <= k; j ++ ) for (int u = 1; u <= m; u ++ ) t[i][j] += a[i][u] * b[u][j]; }