质数相关模板 - l00jj/algorithm GitHub Wiki
注意:
!质数的处理环节放在 static {} 并不一定比放在正式环节内要快,可以尝试更换生成位置看是否有速度提升!
高效提取质因数
class Solution {
private static final int[] MIN_PRIME;
static {
MIN_PRIME = new int[1_000_001];
int[] prime = new int[1_000_001];
int count = 0;
for (int i = 2; i < prime.length; i++) {
if (MIN_PRIME[i] == 0) {
MIN_PRIME[i] = prime[count++] = i;
}
for (int j = 0; j < count && i * prime[j] < prime.length; j++) {
MIN_PRIME[i * prime[j]] = prime[j];
if (i % prime[j] == 0) break;
}
}
}
//【方案一】使用代码,核心在于反复寻找当前最小质因数
for (int num = input; num > 1; num /= MIN_PRIME[num]) {}
// 注意:for循环内逻辑代码部分,使用的是MIN_PRIME[num],不是num
//【方案二】有需要时用一个变量循环剔除重复出现的质数
for (int num = input, same = 0; num > 1; num /= MIN_PRIME[num]) {
if (MIN_PRIME[num] == same) continue;
// 逻辑代码,注意变量用MIN_PRIME[num],而不是num
same = MIN_PRIME[num];
}
}
快速分解质因数,示例代码
// 寻找因数
for (int factor = 2; factor * factor <= num; factor++) {
if (num % factor == 0) {
// 逻辑代码区
// ...
// 找到因数后把对应倍数剔除
while(num % factor == 0) num /= factor;
}
}
// 结果也是一个质因数
if (num > 1) {
// 逻辑代码区
// ...
}
预处理质数筛
函数内使用版
static int[] primes;
static {
int max = (int)1e6; // 最大搜索数
boolean[] visted = new boolean[max + 1];
primes = new int[100];
primes[0] = 2;
primes[1] = 2;
for (int cNum = 2; cNum <= max; cNum += 2) visted[cNum] = true;
for (int num = 3; num <= max; num += 2) {
if (!visted[num]) {
if (primes[0] == primes.length) {
int[] resPrimes = new int[primes.length * 10];
System.arraycopy(primes, 0, resPrimes, 0, primes.length);
primes = resPrimes;
}
primes[primes[0]++] = num;
}
for (int cNum = num; cNum <= max; cNum += num) {
visted[cNum] = true;
}
}
int[] resPrimes = new int[primes[0] - 1];
System.arraycopy(primes, 1, resPrimes, 0, resPrimes.length);
primes = resPrimes;
}
类静态/外置版
class Solution {
private final static int MX = (int) 1e6;
private final static int[] primes = new int[78498];
private final static boolean[] np = new boolean[MX + 1];
static {
int pi = 0;
for (int i = 2; i <= MX; ++i) {
if (!np[i]) {
primes[pi++] = i;
for (int j = i; j <= MX / i; ++j) np[i * j] = true;
}
}
}
}
MX = 10 ** 6 + 1
primes, is_prime = [], [True] * MX
for i in range(2, MX):
if is_prime[i]:
primes.append(i)
for j in range(i * i, MX, i):
is_prime[j] = False
单个数字判断
如果数量不多情况下直接判断更为简单
def is_prime(self, n: int) -> bool:
return all(n % i for i in range(2, isqrt(n) + 1))
is_prime = lambda n: n >= 2 and all(n % i for i in range(2, isqrt(n) + 1))
相关题目: