Project Euler #50: Consecutive prime sum
Difficulty: Hard

<sub>This problem is a programming version of [Problem 50](https://projecteuler.net/problem=50) from [projecteuler.net](https://projecteuler.net/)</sub>  

The prime $41$, can be written as the sum of six consecutive primes:  
$$41 = 2 + 3 + 5 + 7 + 11 + 13$$
 
This is the longest sum of consecutive primes that adds to a prime below one-hundred.  

The longest sum of consecutive primes below one-thousand that adds to a prime, contains $21$ terms, and is equal to $953$.  

Which prime, $\le N$, can be written as the sum of the most consecutive primes?  
**Note:** You have to print prime as well as the length of consecutive chain whose sum is prime. If such primes are more than 1, print the least.  



Input Format:
The first line contains an integer $T$ , i.e., number of test cases.  
Next $T$ lines will contain an integer $N$.


Output Format:
Print the values corresponding to each test case in a new line.


Sample Input:
```raw
2
100
1000
```

Sample Output:
```raw
41 6
953 21
```

Python 3 starter code:


Reference solution (Ruby):
```cs
using System;
using System.Collections.Generic;
using System.IO;
class Solution
{
    static int MAX = 10000000;
    static int[] is_prime = new int[MAX];
    static List<int> primes = new List<int>();  // 664579 number of primes < MAX
    static List<long> psum = new List<long>();

    static int lower_bound(long P)
    {
        int be = 0, en = psum.Count - 1, res = psum.Count - 1;
        while (be <= en)
        {
            int m = (be + en) / 2;
            if (psum[m] >= P)
            {
                res = m;
                en = m - 1;
            }
            else
                be = m + 1;
        }
        return res;
    }

    static bool is_primef(long N)
    {
        if (N < 2) return false;
        for (long i = 2; i * i <= N; ++i)
            if (N % i == 0)
                return false;
        return true;
    }

    static void Main(String[] args)
    {
        for (int i = 0; i < MAX; ++i) is_prime[i] = 1;
        is_prime[0] = is_prime[1] = 0;
        long s = 0;
        for (int i = 0; i < MAX; ++i)
            if (is_prime[i] == 1)
            {
                primes.Add(i);
                s += i;
                psum.Add(s);

                if ((long)i*i >= MAX) continue;
                for (int j = i * i; j < MAX; j += i)
                    is_prime[j] = 0;
            }

        int OPTIMAL_ANSWER_DISTANCE = 20;
        int T = Int32.Parse(Console.ReadLine());
        while (T-- > 0)
        {
            long N = Int64.Parse(Console.ReadLine());
            int index = lower_bound(N);  // first m prime numbers: 2 + 3 + 5 + 7 + ... + p_index >= N
            long bestp = 0, bestl = 0;

            for (int i = Math.Max(0, index - OPTIMAL_ANSWER_DISTANCE); i < Math.Min(index + OPTIMAL_ANSWER_DISTANCE, primes.Count); ++i)
            {
                for (int j = 0; j < 100 && j <= i-bestl; ++j)
                {
                    long act_sum = psum[i] - (j > 0 ? psum[j - 1] : 0);
                    if (act_sum <= N && is_primef(act_sum))
                    {
                        int act_len = i - j + 1;
                        if (act_len > bestl)
                        {
                            bestl = act_len;
                            bestp = act_sum;
                        }
                    }
                }
            }

            Console.WriteLine(bestp + " " + bestl);

            /*int bestp = 1, bestl = 0;
            for (int p = 2; p <= N; ++p)
            {
                // 2 + 3 + 5 + 7 + 11 + 13 + 17 ... + pn = p

                if (is_prime[p] == 0) continue;
                int index = lower_bound(p);
                int sum = 0, i1 = 0;
                for (int i2 = 0; primes[i2] < p; ++i2)
                {
                    sum += primes[i2];
                    while (sum > p)
                        sum -= primes[i1++];
                    if (sum == p)
                    {
                        int l = i2 - i1 + 1;
                        if (l > bestl)
                        {
                            bestp = p;
                            bestl = l;
                        }
                        break;
                    }
                }
                //Console.WriteLine(p + ": " + bestp + " " + bestl + " " + index);
            }*/
        }
    }
}
```