Problem:
Score : 100 points

Problem Statement

There are N children, numbered 1, 2, \ldots, N.

They have decided to share K candies among themselves.
Here, for each i (1 \leq i \leq N), Child i must receive between 0 and a_i candies (inclusive).
Also, no candies should be left over.

Find the number of ways for them to share candies, modulo 10^9 + 7.
Here, two ways are said to be different when there exists a child who receives a different number of candies.

Constraints

All values in input are integers.

1 \leq N \leq 100

0 \leq K \leq 10^5

0 \leq a_i \leq K

Input

Input is given from Standard Input in the following format:

N K
a_1 a_2 \ldots a_N

Output

Print the number of ways for the children to share candies, modulo 10^9 + 7.

Sample Input 1

3 4
1 2 3

Sample Output 1

5

There are five ways for the children to share candies, as follows:

(0, 1, 3)

(0, 2, 2)

(1, 0, 3)

(1, 1, 2)

(1, 2, 1)

Here, in each sequence, the i-th element represents the number of candies that Child i receives.

Sample Input 2

1 10
9

Sample Output 2

0

There may be no ways for the children to share candies.

Sample Input 3

2 0
0 0

Sample Output 3

1

There is one way for the children to share candies, as follows:

(0, 0)

Sample Input 4

4 100000
100000 100000 100000 100000

Sample Output 4

665683269

Be sure to print the answer modulo 10^9 + 7.

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Linq;
using System.Numerics;
using System.Collections.Generic;
using System.IO;
using System.Text;
using N = System.Int64;

public class Solver
{
    N n, k;
    N[] a;
    public void Solve()
    {
        n = ri;
        k = ri;
        a = new N[n];
        for(int i = 0; i < n; i++) { a[i] = ri; }
        N[,] dp = new N[n, k + 1];//dp[i,j]:子供(N-i),...,Nの(i+1)人でk個分ける分け方
        for (int j = 0; j <= a[0]; j++)
        {
            dp[0, j] = 1;
        }
        N u = a[0];
        N[] sum = new N[k];
        for (int i = 1; i < n; i++)
        {
            u += a[i];
            sum = new N[k + 2];//sum[j]:dp[i,0]~dp[i,j-1]の和
            for(int j = 0; j <= k; j++)
            {
                sum[j + 1] = sum[j] + dp[i - 1, j];
            }
            for (int j = 0; j <= u && j <= k; j++)
            {
                dp[i, j] = (sum[j + 1] - sum[Math.Max(0, j - a[i])]) % mod;
            }
        }
        Write(dp[n - 1, k]);
    }

    int ri { get { return sc.Integer(); } }
    long rl { get { return sc.Long(); } }
    double rd { get { return sc.Double(); } }
    string rs { get { return sc.Scan(); } }
    public StreamScanner sc = new StreamScanner(Console.OpenStandardInput());
    public Algorithm alg = new Algorithm();

    private const N mod = 1000000007;
    N ConvFrom2(string x) { N p = 0; for(int i = 0; i < x.Length; i++) { p *= 2; p %= mod; if (x[i] == '1') { p++; } } return p; }
    N Reverse(N n) { return Pow(n, mod - 2); }
    N Mul(params N[] n) { N p = n[0]; for (N i = 1; i < n.Length; i++) { p = (p * n[i]) % mod; } return p; }
    N Pow(N n, N p) { N t = n, q = 1; while (p > 0) { if (p % 2 == 1) { q = (q * t) % mod; } t = (t * t) % mod; p >>= 1; } return q; }
    N PowUpper(N n, N b) { N p = 1; while (p <= n) { p *= b; } return p; }
    N Sign(N n) { return n == 0 ? 0 : n > 0 ? 1 : -1; }
    N Abs(N n) { return (n > 0) ? n : -n; }
    N Gcd(params N[] n) { N p = n[0]; for (N i = 1; i < n.Length; i++) { p = Gcd(p, n[i]); } return p; }
    N Gcd(N a, N b) { return (a == 0) ? b : Gcd(b % a, a); }
    N Lcm(params N[] n) { N p = n[0]; for (N i = 1; i < n.Length; i++) { p = Lcm(p, n[i]); } return p; }
    N Lcm(N a, N b) { return (a / Gcd(a, b) * b) % mod; }
    void Write<T>(T t) { Console.WriteLine(t.ToString()); }
    void YN(bool t) { Console.WriteLine(t ? "YES" : "NO"); }
    void Yn(bool t) { Console.WriteLine(t ? "Yes" : "No"); }
    void yn(bool t) { Console.WriteLine(t ? "yes" : "no"); }
}

static class Program
{
    static public void Main(string[] args)
    {
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        var solver = new Solver();
        solver.Solve();
        Console.Out.Flush();
    }
}

public class Algorithm
{
    public int[] ZAlgorithm(string s)
    {
        int[] p = new int[s.Length];
        p[0] = s.Length;
        int i = 1, j = 0;
        while (i < s.Length)
        {
            while (i + j < s.Length && s[j] == s[i + j]) ++j;
            p[i] = j;
            if (j == 0) { ++i; continue; }
            int k = 1;
            while (i + k < s.Length && k + p[k] < j)
            {
                p[i + k] = p[k];
                ++k;
            }
            i += k; j -= k;
        }
        return p;
    }

    public List<int> SieveOfEratosthenes(int n)
    {
        List<int> l = new List<int>();
        if (n >= 2) { l.Add(2); }
        bool[] t = new bool[(n - 1) / 2];
        for (int p = 3; p <= n; p += 2) { if (!t[(p - 3) / 2]) { l.Add(p); for (int q = p * p; q <= n; q += p) { t[(q - 3) / 2] = true; } } }
        return l;
    }

    public Dictionary<int,int> PrimeFactor(int n, List<int> primetable)
    {
        Dictionary<int, int> d = new Dictionary<int, int>();
        int t = 0;
        foreach(int i in primetable)
        {
            if (n % i == 0)
            {
                while (n % 2 == 0) { n /= i; t++; }
                d.Add(i, t);
            }
        }
        if (n > 1) { d.Add(n, 1); }
        return d;
    }
}

public class PriorityQueue<T> where T : IComparable
{
    private IComparer<T> _comparer = null;
    private int _type = 0;

    private T[] _heap;
    private int _sz = 0;

    private int _count = 0;

    /// <summary>
    /// Priority Queue with custom comparer
    /// </summary>
    public PriorityQueue(IComparer<T> comparer)
    {
        _heap = new T[128];
        _comparer = comparer;
    }

    /// <summary>
    /// Priority queue
    /// </summary>
    /// <param name="type">0: asc, 1:desc</param>
    public PriorityQueue(int type = 0)
    {
        _heap = new T[128];
        _type = type;
    }

    private int Compare(T x, T y)
    {
        if (_comparer != null) return _comparer.Compare(x, y);
        return _type == 0 ? x.CompareTo(y) : y.CompareTo(x);
    }

    public void Push(T x)
    {
        _count++;
        if (_count > _heap.Length)
        {
            var newheap = new T[_heap.Length * 2];
            for (int n = 0; n < _heap.Length; n++) newheap[n] = _heap[n];
            _heap = newheap;
        }

        //node number
        var i = _sz++;

        while (i > 0)
        {
            //parent node number
            var p = (i - 1) / 2;

            if (Compare(_heap[p], x) <= 0) break;

            _heap[i] = _heap[p];
            i = p;
        }

        _heap[i] = x;
    }

    public T Pop()
    {
        _count--;

        T ret = _heap[0];
        T x = _heap[--_sz];

        int i = 0;
        while (i * 2 + 1 < _sz)
        {
            //children
            int a = i * 2 + 1;
            int b = i * 2 + 2;

            if (b < _sz && Compare(_heap[b], _heap[a]) < 0) a = b;

            if (Compare(_heap[a], x) >= 0) break;

            _heap[i] = _heap[a];
            i = a;
        }

        _heap[i] = x;

        return ret;
    }

    public int Count()
    {
        return _count;
    }

    public T Peek()
    {
        return _heap[0];
    }

    public bool Contains(T x)
    {
        for (int i = 0; i < _sz; i++) if (x.Equals(_heap[i])) return true;
        return false;
    }

    public void Clear()
    {
        while (this.Count() > 0) this.Pop();
    }

    public IEnumerator<T> GetEnumerator()
    {
        var ret = new List<T>();

        while (this.Count() > 0)
        {
            ret.Add(this.Pop());
        }

        foreach (var r in ret)
        {
            this.Push(r);
            yield return r;
        }
    }

    public T[] ToArray()
    {
        T[] array = new T[_sz];
        int i = 0;

        foreach (var r in this)
        {
            array[i++] = r;
        }

        return array;
    }
}

public class StreamScanner
{
    public StreamScanner(Stream stream) { str = stream; }
    private readonly Stream str;
    private readonly byte[] buf = new byte[1024];
    private int len, ptr;
    public bool isEof = false;
    public bool IsEndOfStream { get { return isEof; } }
    private byte read()
    {
        if (isEof) throw new EndOfStreamException();
        if (ptr >= len)
        {
            ptr = 0;
            if ((len = str.Read(buf, 0, 1024)) <= 0)
            {
                isEof = true;
                return 0;
            }
        }
        return buf[ptr++];
    }
    public char Char()
    {
        byte b = 0;
        do b = read();
        while (b < 33 || 126 < b);
        return (char)b;
    }
    public string Scan()
    {
        var sb = new StringBuilder();
        for (var b = Char(); b >= 33 && b <= 126; b = (char)read())
            sb.Append(b);
        return sb.ToString();
    }
    public long Long()
    {
        long ret = 0; byte b = 0; var ng = false;
        do b = read();
        while (b != '-' && (b < '0' || '9' < b));
        if (b == '-') { ng = true; b = read(); }
        for (; true; b = read())
        {
            if (b < '0' || '9' < b)
                return ng ? -ret : ret;
            else ret = ret * 10 + b - '0';
        }
    }
    public int Integer() { return (int)Long(); }
    public double Double() { return double.Parse(Scan()); }
}