Welcome to Subscribe On Youtube

3770. Largest Prime from Consecutive Prime Sum

Description

You are given an integer n.

Return the largest prime number less than or equal to n that can be expressed as the sum of one or more consecutive prime numbers starting from 2. If no such number exists, return 0.

 

Example 1:

Input: n = 20

Output: 17

Explanation:

The prime numbers less than or equal to n = 20 which are consecutive prime sums are:

  • 2 = 2

  • 5 = 2 + 3

  • 17 = 2 + 3 + 5 + 7

The largest is 17, so it is the answer.

Example 2:

Input: n = 2

Output: 2

Explanation:

The only consecutive prime sum less than or equal to 2 is 2 itself.

 

Constraints:

  • 1 <= n <= 5 * 105

Solutions

We can preprocess a list of all prime numbers less than or equal to $5 \times 10^5$, then calculate the consecutive prime sums starting from 2, and store those sums that are prime numbers in an array $s$.

For each query, we simply need to use binary search in array $s$ to find the maximum value less than or equal to $n$.

In terms of time complexity, preprocessing the primes takes $O(M \log \log M)$ time, and each query takes $O(\log k)$ time, where $M$ is the upper limit of preprocessing, and $k$ is the length of array $s$. In this problem, $k \leq 40$.

  • class Solution {
        private static final int MX = 500000;
        private static final boolean[] IS_PRIME = new boolean[MX + 1];
        private static final List<Integer> PRIMES = new ArrayList<>();
        private static final List<Integer> S = new ArrayList<>();
    
        static {
            Arrays.fill(IS_PRIME, true);
            IS_PRIME[0] = false;
            IS_PRIME[1] = false;
    
            for (int i = 2; i <= MX; i++) {
                if (IS_PRIME[i]) {
                    PRIMES.add(i);
                    if ((long) i * i <= MX) {
                        for (int j = i * i; j <= MX; j += i) {
                            IS_PRIME[j] = false;
                        }
                    }
                }
            }
    
            S.add(0);
            int t = 0;
            for (int x : PRIMES) {
                t += x;
                if (t > MX) {
                    break;
                }
                if (IS_PRIME[t]) {
                    S.add(t);
                }
            }
        }
    
        public int largestPrime(int n) {
            int i = Collections.binarySearch(S, n + 1);
            if (i < 0) {
                i = ~i;
            }
            return S.get(i - 1);
        }
    }
    
    
  • static const int MX = 500000;
    static vector<bool> IS_PRIME(MX + 1, true);
    static vector<int> PRIMES;
    static vector<int> S;
    
    auto init = [] {
        IS_PRIME[0] = false;
        IS_PRIME[1] = false;
    
        for (int i = 2; i <= MX; i++) {
            if (IS_PRIME[i]) {
                PRIMES.push_back(i);
                if (1LL * i * i <= MX) {
                    for (int j = i * i; j <= MX; j += i) {
                        IS_PRIME[j] = false;
                    }
                }
            }
        }
    
        S.push_back(0);
        int t = 0;
        for (int x : PRIMES) {
            t += x;
            if (t > MX) break;
            if (IS_PRIME[t]) {
                S.push_back(t);
            }
        }
    
        return 0;
    }();
    
    class Solution {
    public:
        int largestPrime(int n) {
            auto it = upper_bound(S.begin(), S.end(), n);
            return *(it - 1);
        }
    };
    
    
  • mx = 500000
    is_prime = [True] * (mx + 1)
    is_prime[0] = is_prime[1] = False
    primes = []
    for i in range(2, mx + 1):
        if is_prime[i]:
            primes.append(i)
            for j in range(i * i, mx + 1, i):
                is_prime[j] = False
    s = [0]
    t = 0
    for x in primes:
        t += x
        if t > mx:
            break
        if is_prime[t]:
            s.append(t)
    
    
    class Solution:
        def largestPrime(self, n: int) -> int:
            i = bisect_right(s, n) - 1
            return s[i]
    
    
  • const MX = 500000
    
    var (
    	isPrime = make([]bool, MX+1)
    	primes  []int
    	S       []int
    )
    
    func init() {
    	for i := range isPrime {
    		isPrime[i] = true
    	}
    	isPrime[0] = false
    	isPrime[1] = false
    
    	for i := 2; i <= MX; i++ {
    		if isPrime[i] {
    			primes = append(primes, i)
    			if i*i <= MX {
    				for j := i * i; j <= MX; j += i {
    					isPrime[j] = false
    				}
    			}
    		}
    	}
    
    	S = append(S, 0)
    	t := 0
    	for _, x := range primes {
    		t += x
    		if t > MX {
    			break
    		}
    		if isPrime[t] {
    			S = append(S, t)
    		}
    	}
    }
    
    func largestPrime(n int) int {
    	i := sort.SearchInts(S, n+1)
    	return S[i-1]
    }
    
    
  • const MX = 500000;
    
    const isPrime: boolean[] = Array(MX + 1).fill(true);
    isPrime[0] = false;
    isPrime[1] = false;
    
    const primes: number[] = [];
    const s: number[] = [];
    
    (function init() {
        for (let i = 2; i <= MX; i++) {
            if (isPrime[i]) {
                primes.push(i);
                if (i * i <= MX) {
                    for (let j = i * i; j <= MX; j += i) {
                        isPrime[j] = false;
                    }
                }
            }
        }
    
        s.push(0);
        let t = 0;
        for (const x of primes) {
            t += x;
            if (t > MX) break;
            if (isPrime[t]) {
                s.push(t);
            }
        }
    })();
    
    function largestPrime(n: number): number {
        const i = _.sortedIndex(s, n + 1) - 1;
        return s[i];
    }
    
    

All Problems

All Solutions