设 p 是满足 x-p>\textit{pre 的最大质数,换言之,p 是小于 x-\textit{pre 的最大质数,这可以预处理质数列表后,用二分查找得到。
[sol1-Python3]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
MX = 1000 P = [0] # 哨兵,避免二分越界 is_prime = [True] * MX for i inrange(2, MX): if is_prime[i]: P.append(i) # 预处理质数列表 for j inrange(i * i, MX, i): is_prime[j] = False
classSolution: defprimeSubOperation(self, nums: List[int]) -> bool: pre = 0 for x in nums: if x <= pre: returnFalse pre = x - P[bisect_left(P, x - pre) - 1] # 减去 < x-pre 的最大质数 returnTrue
publicbooleanprimeSubOperation(int[] nums) { intpre=0; for (int x : nums) { if (x <= pre) returnfalse; intj= lowerBound(primes, x - pre); pre = x - primes[j - 1]; } returntrue; }
// 见 https://www.bilibili.com/video/BV1AP41137w7/ privateintlowerBound(int[] nums, int target) { intleft= -1, right = nums.length; // 开区间 (left, right) while (left + 1 < right) { // 区间不为空 // 循环不变量: // nums[left] < target // nums[right] >= target intmid= left + (right - left) / 2; if (nums[mid] < target) left = mid; // 范围缩小到 (mid, right) else right = mid; // 范围缩小到 (left, mid) } return right; } }
int init = []() { bool np[MX]{}; for (int i = 2; i < MX; ++i) if (!np[i]) { primes.push_back(i); // 预处理质数列表 for (int j = i; j < MX / i; ++j) np[i * j] = true; } return0; }();
classSolution { public: boolprimeSubOperation(vector<int> &nums){ int pre = 0; for (int x: nums) { if (x <= pre) returnfalse; pre = x - *--lower_bound(primes.begin(), primes.end(), x - pre); } returntrue; } };
funcinit() { const mx = 1000 np := [mx]bool{} for i := 2; i < mx; i++ { if !np[i] { p = append(p, i) // 预处理质数列表 for j := i * i; j < mx; j += i { np[j] = true } } } }
funcprimeSubOperation(nums []int)bool { pre := 0 for _, x := range nums { if x <= pre { returnfalse } pre = x - p[sort.SearchInts(p, x-pre)-1] // 减去 < x-pre 的最大质数 } returntrue }
复杂度分析
时间复杂度:O(n\log U),其中 n 为 nums 的长度,U 为 1000 以内的质数个数。