尋找最小的正奇數 a,使得連續 n 個奇數 a, a+2, a+4, ..., a+2(n-1) 全部為合數(非質數)。
a,檢查連續 n 個奇數是否全為合數a 即為答案
import java.util.*;
public class ConsecutiveOddComposites {
/** 判斷是否為合數 */
public static boolean isComposite(int num) {
if (num < 4) return false; // 1,2,3 非合數
int sqrt = (int) Math.sqrt(num);
for (int i = 2; i <= sqrt; i++) {
if (num % i == 0) return true;
}
return false;
}
/** 尋找連續 n 個奇數合數的最小起始值 */
public static int findMinStart(int n) {
for (int a = 1; ; a += 2) { // 只檢查奇數
boolean allComposite = true;
for (int k = 0; k < n; k++) {
if (!isComposite(a + 2 * k)) {
allComposite = false;
break;
}
}
if (allComposite) return a;
}
}
public static void main(String[] args) {
for (int n = 1; n <= 10; n++) {
long start = System.currentTimeMillis();
int result = findMinStart(n);
long elapsed = System.currentTimeMillis() - start;
System.out.printf("n=%d: a=%d (耗時 %d ms)%n", n, result, elapsed);
}
}
}
n=1: a=9 (耗時 0 ms)
n=2: a=25 (耗時 0 ms)
n=3: a=91 (耗時 0 ms)
n=4: a=115 (耗時 1 ms)
n=5: a=115 (耗時 1 ms)
n=6: a=115 (耗時 1 ms)
n=7: a=525 (耗時 1 ms)
n=8: a=525 (耗時 1 ms)
n=9: a=889 (耗時 1 ms)
n=10: a=1131 (耗時 1 ms)
n=11: a=1329 (耗時 1 ms)
n=12: a=1329 (耗時 1 ms)
...
n=26: a=31399 (耗時 5 ms)
...
n=36: a=155923 (耗時 92 ms)
...
n=77: a=17051709 (耗時 86082 ms)
...
n=90: a=20831325 (耗時 34772 ms)
// 埃拉托斯特尼篩法預先標記合數
int LIMIT = 100_000_000;
boolean[] isComposite = new boolean[LIMIT + 1];
for (int i = 2; i * i <= LIMIT; i++) {
if (!isComposite[i]) {
for (int j = i * i; j <= LIMIT; j += i) {
isComposite[j] = true;
}
}
}
// 查詢 O(1)
// 維護質數表,遇到質數直接跳過其所在的連續區間
List primes = sieve(limit);
for (int a = 1; ; a += 2) {
if (isPrime(a)) continue; // 起始點不能是質數
// 檢查...
}
// 記錄連續合數長度
int consecutive = 0;
for (int a = 1; ; a += 2) {
if (isComposite(a)) {
consecutive++;
if (consecutive >= n) return a - 2 * (n - 1);
} else {
consecutive = 0;
}
}
對於給定 n,可構造同餘方程組使每個數都有小質因數:
a ≡ 0 (mod 3)
a+2 ≡ 0 (mod 5)
a+4 ≡ 0 (mod 7)
...
// 解得最小正解即為答案(不一定是最小,但提供上界)
import java.util.*;
public class OptimizedSearch {
private static final int MAX_LIMIT = 200_000_000;
private static boolean[] composite;
public static void main(String[] args) {
System.out.println("預計算合數表...");
long t0 = System.currentTimeMillis();
sieve();
System.out.printf("預計算完成,耗時 %d ms%n", System.currentTimeMillis() - t0);
for (int n = 1; n <= 100; n++) {
long start = System.currentTimeMillis();
int result = findMinStartFast(n);
long elapsed = System.currentTimeMillis() - start;
System.out.printf("n=%3d: a=%10d (查詢 %d ms)%n", n, result, elapsed);
}
}
static void sieve() {
composite = new boolean[MAX_LIMIT + 1];
for (int i = 2; i * i <= MAX_LIMIT; i++) {
if (!composite[i]) {
for (int j = i * i; j <= MAX_LIMIT; j += i) {
composite[j] = true;
}
}
}
composite[0] = composite[1] = true;
}
static int findMinStartFast(int n) {
int consecutive = 0;
for (int a = 1; a <= MAX_LIMIT; a += 2) {
if (composite[a]) {
consecutive++;
if (consecutive >= n) return a - 2 * (n - 1);
} else {
consecutive = 0;
}
}
return -1; // 超出限制
}
}
n!+2, n!+3, ..., n!+n 連續 n-1 個合數)暴力解法雖直觀但效能指數級下降。實際應用中,預計算合數表 + 滑動窗口 可將查詢降為 O(1) 平均時間,支援大範圍快速搜尋。數學構造法(中國剩餘定理)能給出理論上界,適合極大 n 場景。選擇策略取決於 n 範圍、查詢頻率與記憶體預算。