数学知识
一.质数
1.试除法判定质数
bool is_prime(int x)
{
if (x < 2) return false;
for (int i = 2; i <= x / i; i ++ )
if (x % i == 0)
return false;
return true;
}
2.试除法分解质因数
如果是不同质因数,可以用set存储
for (int i = 2; i * i <= num; i++) {
while (num % i == 0) {
// 此时i就是质数,可以存储i
s++;
num /= i;
}
}
// 处理特殊情况
if (num > 1) {
// 此时num就是质数
s++;
}
return s;
3.埃式筛法求素数
class Solution {
public int countPrimes(int n) {
boolean[] isPrim = new boolean[n];
Arrays.fill(isPrim, true);
for (int i = 2; i * i < n; i++) {
//排除不可能为素数的数
if (isPrim[i]) {
for (int j = 2 * i; j < n; j += i) {
isPrim[j] = false;
}
}
}
int count = 0;
for(int i = 2;i<n;i++){
if(isPrim[i]){
count++;
}
}
return count;
}
}
二.约数
1.试除法求所有约数
List<Integer> res = new ArrayList<>();
for (int i = 1; i <= x / i; i++) { // 避免整数溢出,同时减少不必要的迭代
if (x % i == 0) {
res.add(i);
if (i != x / i) { // 避免添加平方数的重复因子
res.add(x / i);
}
}
}
Collections.sort(res); // 对结果进行排序
return res;
2.求约数个数及约数之和
如果 N = p1^c1 * p2^c2 * … *pk^ck ,其中p1…pk是质因数,c1…ck是指数(即质因数出现次数)
约数个数: (c1 + 1) * (c2 + 1) * … * (ck + 1)
约数之和: (p1^0 + p1^1 + … + p1^c1) * … * (pk^0 + pk^1 + … + pk^ck)
3.欧几里得算法–求最大公约数
//a和b无大小关系
private int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
最小公倍数代码如下
long lcm = a / gcd(a, b) * b;
三.快速幂
场景:快速求出 2^k % p
求 m^k mod p,时间复杂度 O(logk)。只求幂的话,去掉 %p 即可
int qmi(int m, int k, int p)
{
int res = 1 % p, t = m;
while (k > 0)
{
if (k&1) res = res * t % p;
t = t * t % p;
k >>= 1;
}
return res;
}
四.卡特兰数
应用:给定n个0和n个1,它们按照某种顺序排成长度为2n的序列,满足任意前缀中0的个数都不少于1的个数的序列的数量为: Cat(n) = C(2n, n) / (n + 1)
五.格雷编码
/**
* 计算第 n 个格雷码
* 格雷码计算公式:G(n) = n xor (n >> 1)
*/
public int gray(int n) {
return n ^ (n >> 1);
}