import java.io.*;
import java.nio.charset.Charset;
import java.util.*;

public class CFCR493B {
    public static void main(String[] args) throws Exception {
        boolean local = System.getProperty("ONLINE_JUDGE") == null;
        boolean async = false;

        Charset charset = Charset.forName("ascii");

        FastIO io = local ? new FastIO(new FileInputStream("E:\\DATABASE\\TESTCASE\\CFCR493B.in"), new FileOutputStream("E:\\DATABASE\\TESTCASE\\CFCR493B.out"), charset) : new FastIO(System.in, System.out, charset);
        Task task = new Task(io);

        if (async) {
            Thread t = new Thread(null, task, "dalt", 1 << 27);
            t.setPriority(Thread.MAX_PRIORITY);
            t.start();
            t.join();
        } else {
            task.run();
        }

        io.flush();
    }

    public static class Task implements Runnable {
        final FastIO io;

        public Task(FastIO io) {
            this.io = io;
        }

        @Override
        public void run() {
            solve();
        }

        public void solve() {
            int n = io.readInt();

            long total = 0;

            for (int i = 0; i < 9; i++) {
                for (int j = 0; j < 9; j++) {
                    if (i >= 5 && j >= 1 || i + j > n) {
                        continue;
                    }
                    total += (n - i - j + 1);
                }
            }

            io.cache.append(total);
        }

    }

    public static class FastIO {
        private final InputStream is;
        private final OutputStream os;
        private final Charset charset;
        private StringBuilder defaultStringBuf = new StringBuilder(1 << 8);
        public final StringBuilder cache = new StringBuilder();

        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastIO(InputStream is, OutputStream os, Charset charset) {
            this.is = is;
            this.os = os;
            this.charset = charset;
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public long readLong() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            long val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public double readDouble() {
            long num = readLong();
            if (next != '.') {
                return num;
            }

            next = read();
            long divisor = 1;
            long later = 0;
            while (next >= '0' && next <= '9') {
                divisor = divisor * 10;
                later = later * 10 + next - '0';
                next = read();
            }

            if (num >= 0) {
                return num + (later / (double) divisor);
            } else {
                return num - (later / (double) divisor);
            }
        }

        public String readString(StringBuilder builder) {
            skipBlank();

            while (next > 32) {
                builder.append((char) next);
                next = read();
            }

            return builder.toString();
        }

        public String readString() {
            defaultStringBuf.setLength(0);
            return readString(defaultStringBuf);
        }

        public int readString(char[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (char) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public int readString(byte[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (byte) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public void flush() {
            try {
                os.write(cache.toString().getBytes(charset));
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        public boolean hasMore() {
            skipBlank();
            return next != -1;
        }
    }

    public static class Memory {
        public static <T> void swap(T[] data, int i, int j) {
            T tmp = data[i];
            data[i] = data[j];
            data[j] = tmp;
        }

        public static <T> int min(T[] data, int from, int to, Comparator<T> cmp) {
            int m = from;
            for (int i = from + 1; i < to; i++) {
                if (cmp.compare(data[m], data[i]) > 0) {
                    m = i;
                }
            }
            return m;
        }

        public static <T> void move(T[] data, int from, int to, int step) {
            int len = to - from;
            step = len - (step % len + len) % len;
            Object[] buf = new Object[len];
            for (int i = 0; i < len; i++) {
                buf[i] = data[(i + step) % len + from];
            }
            System.arraycopy(buf, 0, data, from, len);
        }
    }
}


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Map.Entry;
import java.util.StringTokenizer;
import java.util.TreeMap;

public class Techno19_2F {

	static int MODE = -1;

	static final Comparator<int[]> COMP_ARR = new Comparator<int[]>() {
		public int compare(int[] a1, int[] a2) {
			if (MODE != -1 && (a1.length == 32 || a2.length == 32)) {
				if (a1.length == 32) {
					if (MODE < a2.length) {
						return -1;
					}
					if (MODE > a2.length) {
						return 1;
					}
				} else {
					if (a1.length < MODE) {
						return -1;
					}
					if (a1.length > MODE) {
						return 1;
					}
				}

				for (int i = 0; i < MODE; i++) {
					if (a1[i] < a2[i]) {
						return -1;
					}
					if (a1[i] > a2[i]) {
						return 1;
					}
				}
				return 0;
			} else {
				if (a1.length < a2.length) {
					return -1;
				}
				if (a1.length > a2.length) {
					return 1;
				}

				for (int i = 0; i < a2.length; i++) {
					if (a1[i] < a2[i]) {
						return -1;
					}
					if (a1[i] > a2[i]) {
						return 1;
					}
				}
				return 0;
			}
		}
	};

	static TreeMap<int[], Integer> index = new TreeMap<>(COMP_ARR);
	static int[][] states;

	static ArrayList<int[]> start = new ArrayList<>();

	static int[] numD;

	static int[] pFact = new int[1_000_001];

	static TreeMap<int[], Integer> divCostInd = new TreeMap<>(COMP_ARR);

	public static void main(String[] args) throws IOException {
		cGen = new int[23];
		numD = new int[6000];
		states = new int[6000][];
		genAll(0, 23, 23, 1);

		aList = new ArrayList[6000];
		for (int i = 0; i < 6000; i++) {
			aList[i] = new ArrayList<>();
		}
		fAList();

		divCost = new int[400][301];
		for (int[] a : divCost) {
			Arrays.fill(a, Integer.MAX_VALUE / 2);
		}
		cost = new int[index.size()];

		Arrays.fill(pFact, 1);
		for (int i = 2; i <= 1_000_000; i++) {
			if (pFact[i] == 1) {
				for (int m = i; m <= 1_000_000; m += i) {
					pFact[m] = i;
				}
			}
		}

		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter printer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

		int nT = Integer.parseInt(reader.readLine());

		while (nT-- > 0) {
			StringTokenizer inputData = new StringTokenizer(reader.readLine());
			int a = Integer.parseInt(inputData.nextToken());
			int b = Integer.parseInt(inputData.nextToken());

			int[] aA = toArray(a);
			int[] bA = toArray(b);

			Integer aRes = divCostInd.get(aA);
			if (aRes == null) {
				aRes = divCostInd.size();
				bfs(aA, divCostInd.size());
				divCostInd.put(aA, divCostInd.size());
			}
			Integer bRes = divCostInd.get(bA);
			if (bRes == null) {
				bRes = divCostInd.size();
				bfs(bA, divCostInd.size());
				divCostInd.put(bA, divCostInd.size());
			}

			int minA = Integer.MAX_VALUE / 4;
			for (int nD = 1; nD <= 300; nD++) {
				minA = Math.min(minA, divCost[aRes][nD] + divCost[bRes][nD]);
			}
			printer.println(minA);
		}
		printer.close();
	}

	static int[] toArray(int a) {
		ArrayList<Integer> cnts = new ArrayList<Integer>();
		int last = -1;
		int cCnt = 0;

		while (a > 1) {
			int cPFact = pFact[a];
			if (cPFact == last) {
				cCnt++;
			} else {
				if (cCnt != 0) {
					cnts.add(cCnt);
				}
				last = cPFact;
				cCnt = 1;
			}
			a /= pFact[a];
		}
		if (cCnt != 0) {
			cnts.add(cCnt);
		}
		Collections.sort(cnts, Comparator.reverseOrder());
		int[] res = new int[cnts.size()];
		for (int i = 0; i < cnts.size(); i++) {
			res[i] = cnts.get(i);
		}
		return res;
	}

	static int[] cost;

	static int[][] divCost;

	static void bfs(int[] sState, int searchI) {
		int sInd = index.get(sState);
		ArrayDeque<Integer> queue = new ArrayDeque<>();

		queue.add(index.get(sState));

		Arrays.fill(cost, -1);
		cost[sInd] = 0;

		while (!queue.isEmpty()) {
			int cStInd = queue.remove();
			for (int nStInd : aList[cStInd]) {
				if (cost[nStInd] == -1) {
					cost[nStInd] = cost[cStInd] + 1;
					queue.add(nStInd);
				}
			}
		}

		for (Entry<int[], Integer> cE : index.entrySet()) {
			int cNumD = numD[cE.getValue()];
			if (cNumD <= 300) {
				divCost[searchI][cNumD] = Math.min(divCost[searchI][cNumD], cost[cE.getValue()]);
			}
		}
	}

	static ArrayList<Integer>[] aList;

	static void fAList() {
		int[] cState = new int[32];
		for (Entry<int[], Integer> cE : index.entrySet()) {
			int[] oState = cE.getKey();
			int cStInd = cE.getValue();

			int cLen = states[cStInd].length;
			for (int i = 0; i < cLen; i++) {
				cState[i] = oState[i];
			}
			MODE = cLen;

			for (int i = 0; i < cLen; i++) {
				if (i == 0 || cState[i - 1] > cState[i]) {
					cState[i]++;
					Integer nStInd = index.get(cState);
					cState[i]--;

					if (nStInd == null) {
						continue;
					}
					aList[cStInd].add(nStInd);
				}

				if (i == cLen - 1 && cState[i] == 1) {
					MODE--;
					Integer nStInd = index.get(cState);
					MODE++;
					if (nStInd == null) {
						continue;
					}
					aList[cStInd].add(nStInd);
				} else if (i == cLen - 1 || cState[i] > cState[i + 1]) {
					cState[i]--;
					Integer nStInd = index.get(cState);
					cState[i]++;
					if (nStInd == null) {
						continue;
					}
					aList[cStInd].add(nStInd);
				}
			}
			cState[cLen] = 1;

			MODE++;
			Integer nStInd = index.get(cState);
			MODE--;
			if (nStInd == null) {
				continue;
			}
			aList[cStInd].add(nStInd);
		}
	}

	static int[] cGen;

	static void genAll(int i, int max, int rem, int cProd) {
		numD[index.size()] = cProd;

		int[] cKey = Arrays.copyOf(cGen, i);
		states[index.size()] = cKey;
		index.put(cKey, index.size());

		if (rem > 0) {
			for (int nV = Math.min(max, rem); nV >= 1; nV--) {
				cGen[i] = nV;
				genAll(i + 1, nV, rem - nV, cProd * (nV + 1));
			}
		}
	}
}


import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author sheep
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskE solver = new TaskE();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskE {
    private static final int MOD = 1000000007;
    private static final long[][] choose;
    static {
        choose = new long[55][55];
        for (int i = 0; i <= 51; ++i) {
            choose[i][0] = choose[i][i] = 1;
            for (int j = 1; j < i; ++j) {
                choose[i][j] = (choose[i - 1][j] + choose[i - 1][j - 1]) % MOD;
            }
        }
    }
    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int n = in.nextInt(), k = in.nextInt();

        if (k > n) {
            out.println(0);
            return;
        }

        int[][][] dp = new int[n + 1][2][n + 1];
        dp[1][0][0] = 1;
        dp[0][1][0] = 1;
        for (int i = 2; i <= n; ++i) {
            for (int j = 0; j < 2; ++j) {
                for (int match = 0; match <= i; ++match) {
                    for (int left = 0; left < 2; ++left) {
                        for (int right = 0; right < 2; ++right) {
                            if ((left == 0 || right == 0) && j == 0) continue;
                            if (left == 1 && right == 1 && j == 1) continue;
                            int rem = match - j;
                            if (rem < 0) continue;
                            for (int leftSize = 0; leftSize < i; ++leftSize) {
                                for (int leftMatch = 0; leftMatch <= leftSize && leftMatch <= rem; ++leftMatch) {
                                    int rightSize = i - 1 - leftSize;
                                    int rightMatch = rem - leftMatch;
                                    if (rightMatch > rightSize) continue;
                                    if (leftSize < rightSize || leftSize == rightSize && leftMatch < rightMatch) {
                                        dp[i][j][match] = (int) ((dp[i][j][match] + dp[leftSize][left][leftMatch]
                                                * (long) dp[rightSize][right][rightMatch] % MOD * (i == n ? 1 : i) % MOD * choose[i - 1][leftSize] % MOD) % MOD);
                                    } else if (leftSize == rightSize && leftMatch == rightMatch) {
                                        dp[i][j][match] = (int) ((dp[i][j][match] + dp[leftSize][left][leftMatch]
                                                * (long) (dp[rightSize][right][rightMatch] - 1) % MOD * NumberUtils.powMod(2, MOD - 2, MOD) % MOD * (i == n ? 1 : i) % MOD * choose[i - 1][leftSize] % MOD) % MOD);
                                        dp[i][j][match] = (int) ((dp[i][j][match] + dp[leftSize][left][leftMatch] * (long) (i == n ? 1 : i) % MOD * choose[i - 1][leftSize] % MOD * NumberUtils.powMod(2, MOD - 2, MOD) % MOD) % MOD);
                                    }
//                                    if (i == 3 && j == 1 && match == 1) {
//                                        out.println("left = " + left + " right = " + right + " ls = " + leftSize + " lm = " + leftMatch + " rs = " + rightSize + " rm = " + rightMatch + " i = " + i + " j = " + j + " match = " + match + " res = " + dp[i][j][match]);
//                                    }
                                 }
                            }
                        }
                    }
//                    out.println("i = " + i + " j = " + j + " match = " + match + " res = " + dp[i][j][match]);
                }
            }
        }

        out.println((((dp[n][0][k] + dp[n][1][k]) % MOD) + MOD) % MOD);
    }
}

class InputReader {
    BufferedReader reader;
    StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream));
        tokenizer = null;
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (Exception e) {
                throw new UnknownError();
            }
        }
        return tokenizer.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }

    }

class NumberUtils {

    public static long powMod(long x, long y, long mod) {
        long res = 1;
        for (; y != 0; y >>= 1L) {
            if (y % 2 == 1) res = res * x % mod;
            x = x * x % mod;
        }
        return res;
    }

    }


import java.util.*;
import java.io.*;

public class Main {

	BufferedReader in;
	StringTokenizer str = null;
	PrintWriter out;

	private String next() throws Exception{
		while (str == null || !str.hasMoreElements())
			str = new StringTokenizer(in.readLine());
		return str.nextToken();
	}

	private int nextInt() throws Exception{
		return Integer.parseInt(next());
	}

	private long nextLong() throws Exception{
		return Long.parseLong(next());
	}

	private double nextDouble() throws Exception{
		return Double.parseDouble(next());
	}

	final long MOD = (long)(1e9) + 7;
	long []f;

	final int MAXN = 200010;

	public void run() throws Exception{
		in =  new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		int n = nextInt(), m = nextInt(), g = nextInt();
		if (n == 0) {
			if (m > 1) {
				if (g == 0) {
					out.println(1);
				}else {
					out.println(0);
				}
			}else {
				if (g == 1) {
					out.println(1);
				}else {
					out.println(0);
				}
			}
			out.close();
			return;
		}
		if (m == 0) {
			if (n % 2 == 0) {
				out.println(g);
			}else {
				out.println(g ^ 1);
			}
			out.close();
			return;
		}
		f = new long[MAXN];
		f[0] = 1;
		for(int i = 1; i < MAXN; ++i) f[i] = (f[i-1] * i) % MOD;
		long ret = 0;
		for(int i = 0; i <= n; ++i) {
			if (i % 2 == 0) {
				if (m - 1 > 0 || n - i > 0) {
					if (g == 0) ret += C(m - 1, n - i + m - 1);
				}else {
					if (g == 1) ret += 1;
				}
			}else {
				if (m - 1 > 0 || n - i > 0) {
					if (g == 1) ret += C(m - 1, n - i + m - 1);
				}else {
					if (g == 0) ret += 1;
				}
			}
			if (ret >= MOD) ret -= MOD;
		}
		out.println(ret);
		out.close();
	}

	private long C(int m, int n){
		long ret = f[n];
		ret *= inv((f[m] * f[n - m]) % MOD, MOD);
		return ret % MOD;
	}

	private long inv(long a, long b) {
		return pow(a, b - 2);
	}

	private long pow(long x, long p) {
		long ret = 1;
		while(p > 0) {
			if (p % 2 == 1) ret = (ret * x) % MOD;
			x = (x * x) % MOD;
			p >>= 1;
		}
		return ret;
	}

	public static void main(String[] args) throws Exception{
		new Main().run();
	}
}


import java.io.*;
import java.util.*;

public class C {

	BufferedReader br;
	PrintWriter out;
	StringTokenizer st;
	boolean eof;

	void solve() throws IOException {
		int n = nextInt();
		int m = nextInt();
if (n == 1) {
out.println(1);
return;}
		long allPairs = (long) n * m * (n * m - 1);
		long goodPairs = (long) n * m * (m - 1);
		double p2 = 1.0 * goodPairs / allPairs;
		out.println(1.0 / n + (n - 1.0) / n * p2);
	}

	C() throws IOException {
		br = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		solve();
		out.close();
	}

	public static void main(String[] args) throws IOException {
		new C();
	}

	String nextToken() {
		while (st == null || !st.hasMoreTokens()) {
			try {
				st = new StringTokenizer(br.readLine());
			} catch (Exception e) {
				eof = true;
				return null;
			}
		}
		return st.nextToken();
	}

	String nextString() {
		try {
			return br.readLine();
		} catch (IOException e) {
			eof = true;
			return null;
		}
	}

	int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}

	long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}
}


import java.io.*;import java.util.*;public class codeforces452C{public static void main(String[] args) throws IOException{StringTokenizer st=new StringTokenizer(new BufferedReader(new InputStreamReader(System.in)).readLine());double N=Double.parseDouble(st.nextToken()),M=Double.parseDouble(st.nextToken());System.out.printf("%.12f\n",(N==1&&M==1) ? 1.0 : ((1/N)+((M-1)*(N-1))/(N*(N*M-1))));}}


import java.io.*;
import java.lang.*;
import static java.lang.Math.*;
import java.lang.reflect.*;
import java.math.BigInteger;
import static java.math.BigInteger.*;
import java.security.CodeSource;
import java.security.KeyStore;
import java.util.*;
import static java.util.Arrays.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;

// https://netbeans.org/kb/73/java/editor-codereference_ru.html#display
public class Main {
    //<editor-fold defaultstate="collapsed" desc="Your Fold Super Code">

    private void run() {
        Locale.setDefault(Locale.US);
        boolean oj = true;
        try {
            oj = System.getProperty("MYLOCAL") == null;
        } catch (Exception e) {
        }

        if (oj) {
            sc = new FastScanner(new InputStreamReader(System.in));
            out = new PrintWriter(new OutputStreamWriter(System.out));
        } else {
            try {
                sc = new FastScanner(new FileReader("input.txt"));
                out = new PrintWriter(new FileWriter("output.txt"));
            } catch (IOException e) {
                MLE();
            }
        }
        solve();
        //if( oj )
        err.println("Time: " + (System.currentTimeMillis() - timeBegin) / 1e3);
        out.flush();
    }

    private void show(int[] arr) {
        for( int v : arr ) err.print( " " + v );
        err.println();
    }

    private boolean eq(String a, String b) {
        for( int i = 0; i < a.length(); ++i ){
            if( a.charAt(i) == '.' ) continue;
            if( b.charAt(i) == '.' ) continue;
            if( a.charAt(i) != b.charAt(i) )
                return false;
        }
        return true;
    }

    class FastScanner {

        BufferedReader br;
        StringTokenizer st;

        FastScanner(InputStreamReader reader) {
            br = new BufferedReader(reader);
            st = new StringTokenizer("");
        }

        String next() {
            while (!st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException ex) {
                    Main.MLE();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }
    }

    public static void MLE() {
        int[][] arr = new int[1024 * 1024][];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = new int[1024 * 1024];
        }
    }

    public static void main(String[] args) {
        new Main().run();
    }

    long timeBegin = System.currentTimeMillis();
    FastScanner sc;
    PrintWriter out;
    PrintStream err = System.err;

    // </editor-fold>

    double[] logFact = new double[(int)5e6];
    {
        logFact[0] = log(1);
        for (int i = 1; i < logFact.length; i++) {
            logFact[i] = logFact[i-1] + log(i);
        }
        err.println("f:" + exp(logFact[7]));
    }

    double logC( int m, int n ){
        return logFact[n] - logFact[m] - logFact[n-m];
    }

    void solve() {
        int n = sc.nextInt();
        int m = sc.nextInt();;
        double ans = 0;
        for( int cnt = 1; cnt <= min(n,m); ++cnt ){
            double cur = logC(cnt,m) + logC(n-cnt,n*m-m) - logC(n,n*m);
            if( -50 <= cur  ){
                cur = exp(cur);
                cur = cur * cnt * cnt / n;
                ans += cur;
            }
        }
        out.printf( "%.10f\n", ans);
    }

}


import java.io.*;
import java.lang.*;
import static java.lang.Math.*;
import java.lang.reflect.*;
import java.math.BigInteger;
import static java.math.BigInteger.*;
import java.security.CodeSource;
import java.security.KeyStore;
import java.util.*;
import static java.util.Arrays.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;

// https://netbeans.org/kb/73/java/editor-codereference_ru.html#display
public class Main {
    //<editor-fold defaultstate="collapsed" desc="Your Fold Super Code">

    private void run() {
        Locale.setDefault(Locale.US);
        boolean oj = true;
        try {
            oj = System.getProperty("MYLOCAL") == null;
        } catch (Exception e) {
        }

        if (oj) {
            sc = new FastScanner(new InputStreamReader(System.in));
            out = new PrintWriter(new OutputStreamWriter(System.out));
        } else {
            try {
                sc = new FastScanner(new FileReader("input.txt"));
                out = new PrintWriter(new FileWriter("output.txt"));
            } catch (IOException e) {
                MLE();
            }
        }
        solve();
        //if( oj )
        err.println("Time: " + (System.currentTimeMillis() - timeBegin) / 1e3);
        out.flush();
    }

    private void show(int[] arr) {
        for( int v : arr ) err.print( " " + v );
        err.println();
    }

    private boolean eq(String a, String b) {
        for( int i = 0; i < a.length(); ++i ){
            if( a.charAt(i) == '.' ) continue;
            if( b.charAt(i) == '.' ) continue;
            if( a.charAt(i) != b.charAt(i) )
                return false;
        }
        return true;
    }

    class FastScanner {

        BufferedReader br;
        StringTokenizer st;

        FastScanner(InputStreamReader reader) {
            br = new BufferedReader(reader);
            st = new StringTokenizer("");
        }

        String next() {
            while (!st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException ex) {
                    Main.MLE();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }
    }

    public static void MLE() {
        int[][] arr = new int[1024 * 1024][];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = new int[1024 * 1024];
        }
    }

    public static void main(String[] args) {
        new Main().run();
    }

    long timeBegin = System.currentTimeMillis();
    FastScanner sc;
    PrintWriter out;
    PrintStream err = System.err;

    // </editor-fold>

    static double[] logFact = new double[(int)1e6+1];
    static {
        logFact[0] = log(1);
        for (int i = 1; i < logFact.length; i++) {
            logFact[i] = logFact[i-1] + log(i);
        }
        System.err.println("f:" + exp(logFact[7]));
    }

    double logC( int m, int n ){
        return logFact[n] - logFact[m] - logFact[n-m];
    }

    void solve() {
        int n = sc.nextInt();
        int m = sc.nextInt();;
        double ans = 0;
        for( int cnt = 1; cnt <= min(n,m); ++cnt ){
            double cur = logC(cnt,m) + logC(n-cnt,n*m-m) - logC(n,n*m);
//            if( -50 <= cur  ){
                cur = exp(cur);
                cur = cur * cnt * cnt / n;
                ans += cur;

//            }
        }
        out.printf( "%.10f\n", ans);
    }

}


import java.io.*;
import java.lang.*;
import static java.lang.Math.*;
import java.lang.reflect.*;
import java.math.BigInteger;
import static java.math.BigInteger.*;
import java.security.CodeSource;
import java.security.KeyStore;
import java.util.*;
import static java.util.Arrays.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;

// https://netbeans.org/kb/73/java/editor-codereference_ru.html#display
public class Main {
    //<editor-fold defaultstate="collapsed" desc="Your Fold Super Code">

    private void run() {
        Locale.setDefault(Locale.US);
        boolean oj = true;
        try {
            oj = System.getProperty("MYLOCAL") == null;
        } catch (Exception e) {
        }

        if (oj) {
            sc = new FastScanner(new InputStreamReader(System.in));
            out = new PrintWriter(new OutputStreamWriter(System.out));
        } else {
            try {
                sc = new FastScanner(new FileReader("input.txt"));
                out = new PrintWriter(new FileWriter("output.txt"));
            } catch (IOException e) {
                MLE();
            }
        }
        solve();
        //if( oj )
        err.println("Time: " + (System.currentTimeMillis() - timeBegin) / 1e3);
        out.flush();
    }

    private void show(int[] arr) {
        for( int v : arr ) err.print( " " + v );
        err.println();
    }

    private boolean eq(String a, String b) {
        for( int i = 0; i < a.length(); ++i ){
            if( a.charAt(i) == '.' ) continue;
            if( b.charAt(i) == '.' ) continue;
            if( a.charAt(i) != b.charAt(i) )
                return false;
        }
        return true;
    }

    class FastScanner {

        BufferedReader br;
        StringTokenizer st;

        FastScanner(InputStreamReader reader) {
            br = new BufferedReader(reader);
            st = new StringTokenizer("");
        }

        String next() {
            while (!st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException ex) {
                    Main.MLE();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }
    }

    public static void MLE() {
        int[][] arr = new int[1024 * 1024][];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = new int[1024 * 1024];
        }
    }

    public static void main(String[] args) {
        new Main().run();
    }

    long timeBegin = System.currentTimeMillis();
    FastScanner sc;
    PrintWriter out;
    PrintStream err = System.err;

    // </editor-fold>

    double[] logFact = new double[(int)1e6+1];
    {
        logFact[0] = log(1);
        for (int i = 1; i < logFact.length; i++) {
            logFact[i] = logFact[i-1] + log(i);
        }
        err.println("f:" + exp(logFact[7]));
    }

    double logC( int m, int n ){
        return logFact[n] - logFact[m] - logFact[n-m];
    }

    void solve() {
        int n = sc.nextInt();
        int m = sc.nextInt();;
        double ans = 0;
        for( int cnt = 1; cnt <= min(n,m); ++cnt ){
            double cur = logC(cnt,m) + logC(n-cnt,n*m-m) - logC(n,n*m);
//            if( -50 <= cur  ){
                cur = exp(cur);
                cur = cur * cnt * cnt / n;
                ans += cur;
//            }
        }
        out.printf( "%.10f\n", ans);
    }

}


import java.util.Scanner;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author ASUS
 */
public class NewClass {

public static void main(String[] args) {

    Scanner sc=new Scanner(System.in);
          double m,n;

          n=sc.nextDouble();
          m=sc.nextDouble();

    if ( n == 1 ) {
        System.out. printf ("%.10f", 1. );

    }
    else
    if ( m == 1 ) {
         System.out. printf ("%.10f", 1. / n );

    }
    else
     System.out. printf ("%.10f", 1. / n + ( ( ( n - 1 ) /  n  ) * (  (m - 1 ) / ( n * m - 1 ) ) ) );
     //System.out. printf("%.10lf",1./n+(  ( ( n - 1 ) /  ( n ) )  ));

    System.out.println();
}

}


import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

public class ProblemC {
	static final long MOD = 1000000007;

	public static void main(String[] args) throws IOException {
		Scanner in = new Scanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		int n = in.nextInt();
		long[] a = new long[n];
		for (int i = 0 ; i < n ; i++) {
			a[i] = in.nextLong();
		}
		Arrays.sort(a);

		long best = Long.MAX_VALUE;

		boolean[] isp = new boolean[1000010];
		Arrays.fill(isp, true);
		isp[1] = false;
		for (int i = 2 ; i < 1000010 ; i++) {
			if (isp[i]) {
				for (long ii = 1L * i * i ; ii < 1000010 ; ii += i) {
					isp[(int)ii] = false;
				}
			}
		}
		List<Integer> primes = new ArrayList<Integer>();
		for (int i = 1 ; i < 1000010 ; i++) {
			if (isp[i]) {
				primes.add(i);
			}
		}

		cnt = new long[n];
		for (int i = 0 ; i < n ; i++) {
			long nw = a[i];
			for (int p : primes) {
				while (nw % p == 0) {
					nw /= p;
					cnt[i]++;
				}
			}
			if (nw >= 2) {
				cnt[i]++;
			}
		}
		N = n;

		int[] parent = new int[n];
		Arrays.fill(parent, -1);
		out.println(doit(0, a, parent));
		out.flush();
	}

	static int N;
	static long[] cnt;

	public static long doit(int done, long[] a, int[] parent) {
		if (done == (1<<N)-1) {
			long best = 0;
			for (int i = 0 ; i < N ; i++) {
				long deg = cnt[i];
				boolean hasChild = false;
				for (int j = 0 ; j < N ; j++) {
					if (parent[j] == i) {
						deg -= cnt[j];
						hasChild = true;
					}
				}
				best += deg;
				if (hasChild || cnt[i] >= 2) {
					best++;
				}
			}
			int pcnt = 0;
			for (int j = 0 ; j < N ; j++) {
				if (parent[j] == -1) {
					pcnt++;
				}
			}
			best += (pcnt == 1) ? 0 : 1;
			//debug(pcnt,best);
			return best;
		}
		long best = Long.MAX_VALUE;
		for (int pl = N-1 ; pl >= 0 ; pl--) {
			if ((done & (1<<pl)) != 0) {
				continue;
			}
			for (int p = 0 ; p < N ; p++) {
				if ((done & (1<<p)) == 0) {
					continue;
				}
				if (a[p] % a[pl] == 0) {
					parent[pl] = p;
					long rev = a[p];
					a[p] /= a[pl];
					best = Math.min(best, doit(done | (1<<pl), a, parent));
					a[p] = rev;
					parent[pl] = -1;
				}
			}
			parent[pl] = -1;
			best = Math.min(best, doit(done | (1<<pl), a, parent));
			break;
		}
		return best;
	}

	public static void debug(Object... o) {
		System.err.println(Arrays.deepToString(o));
	}
}


import java.io.*;
import java.util.*;

public class Main implements Runnable {

    public void _main() throws Exception {
	int n = nextInt();
	int m = nextInt();
	int x1 = nextInt();
	int y1 = nextInt();
	int x2 = nextInt();
	int y2 = nextInt();
	int h = Math.abs(x1 - x2) + 1;
	int w = Math.abs(y1 - y2) + 1;
	if ((h >= 4 && w >= 5) || (h >= 5 && w >= 4) || h >= 6 || w >= 6) {
	    out.println("Second");
	} else {
	    out.println("First");
	}
    }

    private BufferedReader in;
    private PrintWriter out;
    private StringTokenizer st;

    private String next() throws IOException {
        while (st == null || !st.hasMoreTokens()) {
            String rl = in.readLine();
            if (rl == null) return null;
            st = new StringTokenizer(rl);
        }
        return st.nextToken();
    }

    private int nextInt() throws IOException {
        return Integer.parseInt(next());
    }

    private long nextLong() throws IOException {
        return Long.parseLong(next());
    }

    private double nextDouble() throws IOException {
        return Double.parseDouble(next());
    }

    public void run() {
        try {
            in = new BufferedReader(new InputStreamReader(System.in));
            out = new PrintWriter(System.out);

            _main();

            out.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(202);
        }
    }

    public static void main(String[] args) {
        new Thread(new Main()).run();
    }

}


import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Scanner;
import java.util.Vector;
public class Main {
	static final long mod=1000000007;
	public static void main(String[] args) {
		long a[]=new long[20];
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		long s=sc.nextLong();
		for(int i=0;i<n;i++)
				a[i]=sc.nextLong();
		int len=(1<<n);
		long ans=0;
		for(int i=0;i<len;i++){
			long x=s;
			int flag=1;
			for(int j=0;j<n;j++)
				if(((i>>j)&1)==1){
					flag*=-1;
					x-=a[j]+1;
				}
			if(x<0)
				continue;
			ans=(ans+flag*lucas(x+n-1,n-1))%mod;
			ans=(ans+mod)%mod;
		}
		System.out.println(ans);
	}
	static long lucas(long a,long b){
		if(b==0)
			return 1;
		return getc(a%mod,b%mod)*lucas(a/mod,b/mod)%mod;
	}
	static long getc(long a,long b){
		if(a<b)
			return 0;
		long ans=1;
		for(long i=a-b+1;i<=a;i++)
			ans=ans*i%mod;
		long t=1;
		for(long i=1;i<=b;i++)
			t=t*i%mod;
		return ans*qpow(t,mod-2)%mod;
	}
	static long qpow(long a,long b){
		long ans=1;
		while(b!=0){
			if((b&1)==1){
				ans=a*ans%mod;
			}
			a=a*a%mod;
			b>>=1;
		}
		return ans;
	}
}


import java.io.BufferedWriter;
import java.util.InputMismatchException;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.math.BigInteger;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.io.IOException;
import java.util.Arrays;
import java.io.InputStream;
import java.io.OutputStreamWriter;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        TaskE solver = new TaskE();
        solver.solve(1, in, out);
        out.close();
    }
}

class TaskE {
    public void solve(int testNumber, InputReader in, OutputWriter out) {
        int n=in.readInt(), MOD=1000000007;
        long s=in.readLong(), ret=0;
        long[] F= IOUtils.readLongArray(in, n), revFac=IntegerUtils.generateReverseFactorials(n, MOD);
        for (int mask=0; mask<1<<n; mask++) {
            long used=0;
            for (int i=0; i<n; i++) if ((mask&(1<<i))>0)  used+=F[i]+1;
            if (used>s) continue;
            long s2=s-used, x=revFac[n-1];
            for (int i=1; i<n; i++) x=(s2+n-i)%MOD*x%MOD;
            ret=(ret+(Integer.bitCount(mask)%2==0?1:-1)*x+MOD)%MOD;
        }
        out.printLine(ret);
    }
}

class InputReader {

    private InputStream stream;
    private byte[] buf = new byte[1024];
    private int curChar;
    private int numChars;
    private SpaceCharFilter filter;

    public InputReader(InputStream stream) {
        this.stream = stream;
    }

    public int read() {
        if (numChars == -1)
            throw new InputMismatchException();
        if (curChar >= numChars) {
            curChar = 0;
            try {
                numChars = stream.read(buf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (numChars <= 0)
                return -1;
        }
        return buf[curChar++];
    }

    public int readInt() {
        int c = read();
        while (isSpaceChar(c))
            c = read();
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        int res = 0;
        do {
            if (c < '0' || c > '9')
                throw new InputMismatchException();
            res *= 10;
            res += c - '0';
            c = read();
        } while (!isSpaceChar(c));
        return res * sgn;
    }

    public long readLong() {
        int c = read();
        while (isSpaceChar(c))
            c = read();
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        long res = 0;
        do {
            if (c < '0' || c > '9')
                throw new InputMismatchException();
            res *= 10;
            res += c - '0';
            c = read();
        } while (!isSpaceChar(c));
        return res * sgn;
    }

    public boolean isSpaceChar(int c) {
        if (filter != null)
            return filter.isSpaceChar(c);
        return isWhitespace(c);
    }

    public static boolean isWhitespace(int c) {
        return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
    }

    public interface SpaceCharFilter {
        public boolean isSpaceChar(int ch);
    }
}

class OutputWriter {
    private final PrintWriter writer;

    public OutputWriter(OutputStream outputStream) {
        writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
    }

    public void close() {
        writer.close();
    }

    public void printLine(long i) {
        writer.println(i);
    }

}

class IOUtils {

    public static long[] readLongArray(InputReader in, int size) {
        long[] array = new long[size];
        for (int i = 0; i < size; i++)
            array[i] = in.readLong();
        return array;
    }

}

class IntegerUtils {

    public static long[] generateReverse(int upTo, long module) {
        long[] result = new long[upTo];
        if (upTo > 1)
            result[1] = 1;
        for (int i = 2; i < upTo; i++)
            result[i] = (module - module / i * result[((int) (module % i))] % module) % module;
        return result;
    }

    public static long[] generateReverseFactorials(int upTo, long module) {
        long[] result = generateReverse(upTo, module);
        if (upTo > 0)
            result[0] = 1;
        for (int i = 1; i < upTo; i++)
            result[i] = result[i] * result[i - 1] % module;
        return result;
    }

}


import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.*;

public class DevuAndFlowers {

	static long mod = 1000000007;
	static long modInv[];
	static int N;
	static long S;
	static long f[];
	static long fact[];
	public static void main(String[] args) {
		JS in = new JS();
		N = in.nextInt();
		S = in.nextLong();
		f = new long[N];
		for(int i = 0; i < N; i++) f[i] = in.nextLong();
		modInv = new long[N+5];
		for(int i = 0; i <= N+4; i++) modInv[i] = pow(i, mod-2);

		long ans = 0;
		for(int i = 0; i < (1<<N); i++) {
			long over = S;
			for(int j = 0; j < N; j++) {
				if((i & (1<<j)) > 0) {
					over -= f[j]+1;
				}
			}
			if(over < 0) continue;
			long v = sumTo(over, N);
			if(Integer.bitCount(i)%2==1) ans -= v;
			else ans += v;
			while(ans < 0) ans+=mod;
			while(ans >= mod)ans-=mod;
		}
		System.out.println(ans);
	}

	static long sumTo(long sum, long n) {
		return choose(sum+n-1, n-1);
	}
	static long choose(long n, long k) {
		long prev = 1;
		for(int c = 1; c <= k; c++)
			prev = (((prev*(n%mod-c+1))%mod)*modInv[c])%mod;
		while(prev < 0) prev += mod;
		while(prev >= mod) prev -= mod;
		return prev;
	}

	static long pow(long base, long power) {
		if(power == 0) return 1;
		if(power == 1) return base;
		if((power%2)==0) {
			long r = pow(base, power/2);
			return (r*r)%mod;
		}
		else {
			return (base * pow(base,power-1))%mod;
		}
	}

	static class JS{
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public JS() {
			in = new BufferedInputStream(System.in, BS);
		}

		public JS(String s) throws FileNotFoundException {
			in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}

		public int []nia(int n){
			int r[] = new int[n];
			for(int i = 0; i < n; i++) r[i] = nextInt();
			return r;
		}
		public double []nda(int n){
			double r[] = new double[n];
			for(int i = 0; i < n; i++) r[i] = nextDouble();
			return r;
		}
		public long []nla(int n){
			long r[] = new long[n];
			for(int i = 0; i < n; i++) r[i] = nextLong();
			return r;
		}
	}

}


//package round258;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class E {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni();
		long s = nl();
		long[] a = new long[n];
		for(int i = 0;i < n;i++)a[i] = nl();
		int mod = 1000000007;
		long ret = 0;
		for(int i = 0;i < 1<<n;i++){ // used
			long sum = 0;
			for(int j = 0;j < n;j++){
				if(i<<31-j<0)sum += a[j]+1;
			}
			long rem = s-sum;
			if(rem < 0)continue;
			long val = 1;
			long N = rem+n-1, R = n-1;
			for(int j = 1;j <= R;j++){
				val = val * ((N-j+1)%mod) % mod * invl(j, mod) % mod;
			}
			if(Integer.bitCount(i) % 2 == 0){
				ret += val;
			}else{
				ret += mod-val;
			}
		}
		out.println(ret%mod);
	}

	public static long invl(long a, long mod) {
		long b = mod;
		long p = 1, q = 0;
		while (b > 0){
			long c = a / b;
			long d;
			d = a;
			a = b;
			b = d % b;
			d = p;
			p = q;
			q = d - c * q;
		}
		return p < 0 ? p + mod : p;
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new E().run(); }

	private byte[] inbuf = new byte[1024];
	private int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


import java.io.*;
import java.util.*;
import java.math.*;
import java.util.concurrent.*;

public final class devu_and_flowers
{
    static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	static FastScanner sc=new FastScanner(br);
    static PrintWriter out=new PrintWriter(System.out);
	static Random rnd=new Random();
	static long mod=(long)(1e9+7);

	static long C(long n,long diff)
	{
		long ret=1,upper=n+diff-1;

		for(long x=upper;x>diff;x--)
		{
			long now=x%mod;

			ret=(ret*now)%mod;
		}

		return (ret*pow(fact(n-1),mod-2))%mod;
	}

	static long fact(long n)
	{
		long ret=1;

		for(long i=1;i<=n;i++)
		{
			ret=(ret*i)%mod;
		}

		return ret;
	}

	static long pow(long a,long b)
	{
		long x=1,y=a;

		while(b>0)
		{
			if(b%2==1)
			{
				x=(x*y)%mod;
			}

			y=(y*y)%mod;b=b/2;
		}

		return x;
	}

	static Map<Long,Long> merge(Map<Long,Long> m1,long now)
	{
		Map<Long,Long> m2=new HashMap<>(),ret=new HashMap<>();

		m2.put(0L,1L);m2.put(now,(-1L+mod)%mod);

		for(Map.Entry<Long,Long> en1:m1.entrySet())
		{
			for(Map.Entry<Long,Long> en2:m2.entrySet())
			{
				long add=en1.getKey()+en2.getKey(),mul=(en1.getValue()*en2.getValue())%mod;

				ret.put(add,(ret.getOrDefault(add,0L)+mul)%mod);
			}
		}

		return ret;
	}

    public static void main(String args[]) throws Exception
    {
		int n=sc.nextInt();long s=sc.nextLong();

		long[] a=new long[n];

		for(int i=0;i<n;i++)
		{
			a[i]=sc.nextLong();
		}

		// 1-x^a[i]+1..

		Map<Long,Long> m1=new HashMap<>();m1.put(0L,1L);

		for(int i=0;i<n;i++)
		{
			m1=merge(m1,a[i]+1);
		}

		long res=0;

		for(Map.Entry<Long,Long> en:m1.entrySet())
		{
			long curr=en.getKey();

			if(curr<=s)
			{
				long diff=s-curr;

				long now=C(n,diff);

				long mul=(en.getValue()*now)%mod;

				res=(res+mul)%mod;
			}
		}

		out.println(res);out.close();
    }

	private static class Pair
	{
		long pow,cof;

		public Pair(long pow,long cof)
		{
			this.pow=pow;this.cof=cof;
		}
	}
}
class FastScanner
{
    BufferedReader in;
    StringTokenizer st;

    public FastScanner(BufferedReader in) {
        this.in = in;
    }

    public String nextToken() throws Exception {
        while (st == null || !st.hasMoreTokens()) {
            st = new StringTokenizer(in.readLine());
        }
        return st.nextToken();
    }

	public String next() throws Exception {
		return nextToken().toString();
	}

    public int nextInt() throws Exception {
        return Integer.parseInt(nextToken());
    }

    public long nextLong() throws Exception {
        return Long.parseLong(nextToken());
    }

    public double nextDouble() throws Exception {
        return Double.parseDouble(nextToken());
    }
}


import java.util.ArrayList;
import java.util.Scanner;

public class e {
	static final long MOD = (long)1e9+7;
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		long[] invs = new long[25];
		invs[1] = 1;
		for (int i = 2; i < invs.length; ++i)
			invs[i] = (MOD - (MOD / i) * invs[((int) (MOD % i))] % MOD) % MOD;
		int n = in.nextInt();
		long s = in.nextLong();
		long[] fs = new long[n];
		for(int i=0;i<n;i++)
			fs[i] = in.nextLong();
		ArrayList<Term> ans = new ArrayList<>();
		ArrayList<ArrayList<Term>> eqList = new ArrayList<>();
		for(int i=0;i<n;i++) {
			ArrayList<Term> cur = new ArrayList<>();
			cur.add(new Term(1,0));
			cur.add(new Term(-1,fs[i]+1));
			eqList.add(cur);
		}
		multiply(ans, eqList, 0, new Term(1, 0));
		long sum = 0;
		for(Term t : ans) {
			long pow = s - t.pow;
			if(pow < 0) continue;
			long choose = 1;
			for(int i=0;i<n-1;i++) {
				choose *= (pow+n-1-i) % MOD;
				choose %= MOD;
				choose *= invs[i+1];
				choose %= MOD;
			}
			sum += t.c * choose;
			sum %= MOD;
		}
		if(sum < 0) sum += MOD;
		System.out.println(sum);
	}
	static void multiply(ArrayList<Term> ans, ArrayList<ArrayList<Term>> list, int idx, Term current) {
		if(idx == list.size()) {
			ans.add(current);
			return;
		}
		for(Term t : list.get(idx)) {
			Term nt = new Term((t.c * current.c) % MOD, t.pow + current.pow);
			multiply(ans, list, idx+1, nt);
		}
	}
	static class Term {
		long c;
		long pow;
		public Term(long c, long pow) {
			this.c = c;
			this.pow = pow;
		}
	}
}


import java.awt.*;
import java.io.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.List;

import static java.lang.Math.max;
import static java.lang.Math.min;

public class E implements Runnable{

    // SOLUTION!!!
    // HACK ME PLEASE IF YOU CAN!!!
    // PLEASE!!!
    // PLEASE!!!
    // PLEASE!!!

    private final static Random rnd = new Random();
    private final static String fileName = "";

    final static long MODULO = 1000 * 1000 * 1000 + 7;

    long inverseNMinus1Factorial;

    private void solve() {
        int n = readInt();
        long s = readLong();

        long[] f = readLongArray(n);

        Map<Long, Long> coeffs = new HashMap<>();
        coeffs.put(0L, 1L);

        class Pair {
            long power, coeff;

            public Pair(long power, long coeff) {
                this.power = power;
                this.coeff = coeff;
            }
        }

        for (long size : f) {
            List<Pair> coeffEntries = new ArrayList<>();
            for (Map.Entry<Long, Long> coeffEntry : coeffs.entrySet()) {
                long power = coeffEntry.getKey();
                long coeff = coeffEntry.getValue();

                long nextPower = power + size + 1;
                coeffEntries.add(
                    new Pair(
                        nextPower, -coeff
                    )
                );
            }

            for (Pair coeffEntry : coeffEntries) {
                coeffs.put(coeffEntry.power,
                        add(coeffs.getOrDefault(coeffEntry.power, 0L), coeffEntry.coeff)
                );
            }
        }

        long nMinus1Factorial = multSequence(1, n - 1);
        this.inverseNMinus1Factorial = inverse(nMinus1Factorial);

        long answer = 0;
        for (Map.Entry<Long, Long> coeffEntry : coeffs.entrySet()) {
            long power = coeffEntry.getKey();
            long coeff = coeffEntry.getValue();

            if (s >= power) {
                long need = s - power;
                answer = add(answer, mult(binom(n + need - 1, need), coeff));
            }
        }

        out.println(answer);
    }

    long multSequence(long start, long end) {
        long res = 1;
        for (long i = start; i <= end; ++i) {
            res = mult(res, i);
        }

        return res;
    }

    long inverse(long x) {
        return binpow(x, MODULO - 2);
    }

    long binpow(long base, long power) {
        if (power == 0) return 1;

        if ((power & 1) == 0) {
            long half = binpow(base, power >> 1);
            return mult(half, half);
        } else {
            long prev = binpow(base, power - 1);
            return mult(prev, base);
        }
    }

    long binom(long n, long k) {
        return mult(
                multSequence(k + 1, n),
                inverseNMinus1Factorial
        );
    }

    long add(long a, long b) {
        return ((a % MODULO + b % MODULO) % MODULO + MODULO) % MODULO;
    }

    long mult(long a, long b) {
        return (a % MODULO) * (b % MODULO) % MODULO;
    }

    /////////////////////////////////////////////////////////////////////

    private final static boolean FIRST_INPUT_STRING = false;
    private final static boolean MULTIPLE_TESTS = true;
    private final boolean ONLINE_JUDGE = System.getProperty("ONLINE_JUDGE") != null;

    private final static int MAX_STACK_SIZE = 128;

    private final static boolean OPTIMIZE_READ_NUMBERS = true;

    /////////////////////////////////////////////////////////////////////

    public void run(){
        try{
            timeInit();
            Locale.setDefault(Locale.US);

            init();

            if (ONLINE_JUDGE) {
                solve();
            } else {
                do {
                    try {
                        timeInit();
                        solve();
                        time();

                        out.println();
                    } catch (NumberFormatException e) {
                        break;
                    } catch (NullPointerException e) {
                        if (FIRST_INPUT_STRING) break;
                        else throw e;
                    }
                } while (MULTIPLE_TESTS);
            }

            out.close();
            time();
        }catch (Exception e){
            e.printStackTrace(System.err);
            System.exit(-1);
        }
    }

    /////////////////////////////////////////////////////////////////////

    private BufferedReader in;
    private OutputWriter out;
    private StringTokenizer tok = new StringTokenizer("");

    public static void main(String[] args){
        new Thread(null, new E(), "", MAX_STACK_SIZE * (1L << 20)).start();
    }

    /////////////////////////////////////////////////////////////////////

    private void init() throws FileNotFoundException{
        Locale.setDefault(Locale.US);

        if (ONLINE_JUDGE){
            if (fileName.isEmpty()) {
                in = new BufferedReader(new InputStreamReader(System.in));
                out = new OutputWriter(System.out);
            } else {
                in = new BufferedReader(new FileReader(fileName + ".in"));
                out = new OutputWriter(fileName + ".out");
            }
        }else{
            in = new BufferedReader(new FileReader("input.txt"));
            out = new OutputWriter("output.txt");
        }
    }

    ////////////////////////////////////////////////////////////////

    private long timeBegin;

    private void timeInit() {
        this.timeBegin = System.currentTimeMillis();
    }

    private void time(){
        long timeEnd = System.currentTimeMillis();
        System.err.println("Time = " + (timeEnd - timeBegin));
    }

    private void debug(Object... objects){
        if (ONLINE_JUDGE){
            for (Object o: objects){
                System.err.println(o.toString());
            }
        }
    }

    /////////////////////////////////////////////////////////////////////

    private String delim = " ";

    private String readLine() {
        try {
            return in.readLine();
        } catch (IOException e) {
            throw new RuntimeIOException(e);
        }
    }

    private String readString() {
        try {
            while(!tok.hasMoreTokens()){
                tok = new StringTokenizer(readLine());
            }

            return tok.nextToken(delim);
        } catch (NullPointerException e) {
            return null;
        }
    }

    /////////////////////////////////////////////////////////////////

    private final char NOT_A_SYMBOL = '\0';

    private char readChar() {
        try {
            int intValue = in.read();

            if (intValue == -1){
                return NOT_A_SYMBOL;
            }

            return (char) intValue;
        } catch (IOException e) {
            throw new RuntimeIOException(e);
        }
    }

    private char[] readCharArray() {
        return readLine().toCharArray();
    }

    private char[][] readCharField(int rowsCount) {
        char[][] field = new char[rowsCount][];
        for (int row = 0; row < rowsCount; ++row) {
            field[row] = readCharArray();
        }

        return field;
    }

    /////////////////////////////////////////////////////////////////

    private long optimizedReadLong() {
        int sign = 1;
        long result = 0;
        boolean started = false;
        while (true) {
            try {
                int j = in.read();
                if (-1 == j) {
                    if (started) return sign * result;
                    throw new NumberFormatException();
                }

                if (j == '-') {
                    if (started) throw new NumberFormatException();
                    sign = -sign;
                }

                if ('0' <= j && j <= '9') {
                    result = result * 10 + j - '0';
                    started = true;
                } else if (started) {
                    return sign * result;
                }
            } catch (IOException e) {
                throw new RuntimeIOException(e);
            }
        }
    }

    private int readInt() {

        if (!OPTIMIZE_READ_NUMBERS) {
            return Integer.parseInt(readString());
        } else {
            return (int) optimizedReadLong();
        }
    }

    private int[] readIntArray(int size) {
        int[] array = new int[size];

        for (int index = 0; index < size; ++index){
            array[index] = readInt();
        }

        return array;
    }

    private int[] readSortedIntArray(int size) {
        Integer[] array = new Integer[size];

        for (int index = 0; index < size; ++index) {
            array[index] = readInt();
        }
        Arrays.sort(array);

        int[] sortedArray = new int[size];
        for (int index = 0; index < size; ++index) {
            sortedArray[index] = array[index];
        }

        return sortedArray;
    }

    private int[] readIntArrayWithDecrease(int size) {
        int[] array = readIntArray(size);

        for (int i = 0; i < size; ++i) {
            array[i]--;
        }

        return array;
    }

    ///////////////////////////////////////////////////////////////////

    private int[][] readIntMatrix(int rowsCount, int columnsCount) {
        int[][] matrix = new int[rowsCount][];

        for (int rowIndex = 0; rowIndex < rowsCount; ++rowIndex) {
            matrix[rowIndex] = readIntArray(columnsCount);
        }

        return matrix;
    }

    private int[][] readIntMatrixWithDecrease(int rowsCount, int columnsCount) {
        int[][] matrix = new int[rowsCount][];

        for (int rowIndex = 0; rowIndex < rowsCount; ++rowIndex) {
            matrix[rowIndex] = readIntArrayWithDecrease(columnsCount);
        }

        return matrix;
    }

    ///////////////////////////////////////////////////////////////////

    private long readLong() {
        if (!OPTIMIZE_READ_NUMBERS) {
            return Long.parseLong(readString());
        } else {
            return optimizedReadLong();
        }
    }

    private long[] readLongArray(int size) {
        long[] array = new long[size];

        for (int index = 0; index < size; ++index){
            array[index] = readLong();
        }

        return array;
    }

    ////////////////////////////////////////////////////////////////////

    private double readDouble() {
        return Double.parseDouble(readString());
    }

    private double[] readDoubleArray(int size) {
        double[] array = new double[size];

        for (int index = 0; index < size; ++index){
            array[index] = readDouble();
        }

        return array;
    }

    ////////////////////////////////////////////////////////////////////

    private BigInteger readBigInteger() {
        return new BigInteger(readString());
    }

    private BigDecimal readBigDecimal() {
        return new BigDecimal(readString());
    }

    /////////////////////////////////////////////////////////////////////

    private Point readPoint() {
        int x = readInt();
        int y = readInt();
        return new Point(x, y);
    }

    private Point[] readPointArray(int size) {
        Point[] array = new Point[size];

        for (int index = 0; index < size; ++index){
            array[index] = readPoint();
        }

        return array;
    }

    /////////////////////////////////////////////////////////////////////

    @Deprecated
    private List<Integer>[] readGraph(int vertexNumber, int edgeNumber) {
        @SuppressWarnings("unchecked")
        List<Integer>[] graph = new List[vertexNumber];

        for (int index = 0; index < vertexNumber; ++index){
            graph[index] = new ArrayList<>();
        }

        while (edgeNumber-- > 0){
            int from = readInt() - 1;
            int to = readInt() - 1;

            graph[from].add(to);
            graph[to].add(from);
        }

        return graph;
    }

    private static class GraphBuilder {

        final int size;
        final List<Integer>[] edges;

        static GraphBuilder createInstance(int size) {
            List<Integer>[] edges = new List[size];
            for (int v = 0; v < size; ++v) {
                edges[v] = new ArrayList<>();
            }

            return new GraphBuilder(edges);
        }

        private GraphBuilder(List<Integer>[] edges) {
            this.size = edges.length;
            this.edges = edges;
        }

        public void addEdge(int from, int to) {
            addDirectedEdge(from, to);
            addDirectedEdge(to, from);
        }

        public void addDirectedEdge(int from, int to) {
            edges[from].add(to);
        }

        public int[][] build() {
            int[][] graph = new int[size][];
            for (int v = 0; v < size; ++v) {
                List<Integer> vEdges = edges[v];
                graph[v] = castInt(vEdges);
            }

            return graph;
        }
    }

    /////////////////////////////////////////////////////////////////////

    private static class IntIndexPair {

        static Comparator<IntIndexPair> increaseComparator = new Comparator<E.IntIndexPair>() {

            @Override
            public int compare(E.IntIndexPair indexPair1, E.IntIndexPair indexPair2) {
                int value1 = indexPair1.value;
                int value2 = indexPair2.value;

                if (value1 != value2) return value1 - value2;

                int index1 = indexPair1.index;
                int index2 = indexPair2.index;

                return index1 - index2;
            }
        };

        static Comparator<IntIndexPair> decreaseComparator = new Comparator<E.IntIndexPair>() {

            @Override
            public int compare(E.IntIndexPair indexPair1, E.IntIndexPair indexPair2) {
                int value1 = indexPair1.value;
                int value2 = indexPair2.value;

                if (value1 != value2) return -(value1 - value2);

                int index1 = indexPair1.index;
                int index2 = indexPair2.index;

                return index1 - index2;
            }
        };

        int value, index;

        IntIndexPair(int value, int index) {
            super();
            this.value = value;
            this.index = index;
        }

        int getRealIndex() {
            return index + 1;
        }
    }

    private IntIndexPair[] readIntIndexArray(int size) {
        IntIndexPair[] array = new IntIndexPair[size];

        for (int index = 0; index < size; ++index) {
            array[index] = new IntIndexPair(readInt(), index);
        }

        return array;
    }

    /////////////////////////////////////////////////////////////////////

    private static class OutputWriter extends PrintWriter {

        final int DEFAULT_PRECISION = 12;

        private int precision;
        private String format, formatWithSpace;

        {
            precision = DEFAULT_PRECISION;

            format = createFormat(precision);
            formatWithSpace = format + " ";
        }

        OutputWriter(OutputStream out) {
            super(out);
        }

        OutputWriter(String fileName) throws FileNotFoundException {
            super(fileName);
        }

        int getPrecision() {
            return precision;
        }

        void setPrecision(int precision) {
            precision = max(0, precision);
            this.precision = precision;

            format = createFormat(precision);
            formatWithSpace = format + " ";
        }

        String createFormat(int precision){
            return "%." + precision + "f";
        }

        @Override
        public void print(double d){
            printf(format, d);
        }

        void printWithSpace(double d){
            printf(formatWithSpace, d);
        }

        void printAll(double...d){
            for (int i = 0; i < d.length - 1; ++i){
                printWithSpace(d[i]);
            }

            print(d[d.length - 1]);
        }

        @Override
        public void println(double d){
            printlnAll(d);
        }

        void printlnAll(double... d){
            printAll(d);
            println();
        }
    }

    /////////////////////////////////////////////////////////////////////

    private static class RuntimeIOException extends RuntimeException {

        /**
         *
         */
        private static final long serialVersionUID = -6463830523020118289L;

        RuntimeIOException(Throwable cause) {
            super(cause);
        }
    }

    /////////////////////////////////////////////////////////////////////
    //////////////// Some useful constants and functions ////////////////
    /////////////////////////////////////////////////////////////////////

    private static final int[][] steps = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    private static final int[][] steps8 = {
            {-1, 0}, {1, 0}, {0, -1}, {0, 1},
            {-1, -1}, {1, 1}, {1, -1}, {-1, 1}
    };

    private static boolean checkCell(int row, int rowsCount, int column, int columnsCount) {
        return checkIndex(row, rowsCount) && checkIndex(column, columnsCount);
    }

    private static boolean checkIndex(int index, int lim){
        return (0 <= index && index < lim);
    }

    /////////////////////////////////////////////////////////////////////

    private static boolean checkBit(int mask, int bit){
        return (mask & (1 << bit)) != 0;
    }
    private static boolean checkBit(long mask, int bit){
        return (mask & (1L << bit)) != 0;
    }

    /////////////////////////////////////////////////////////////////////

    private static long getSum(int[] array) {
        long sum = 0;
        for (int value: array) {
            sum += value;
        }

        return sum;
    }

    private static Point getMinMax(int[] array) {
        int min = array[0];
        int max = array[0];

        for (int index = 0, size = array.length; index < size; ++index, ++index) {
            int value = array[index];

            if (index == size - 1) {
                min = min(min, value);
                max = max(max, value);
            } else {
                int otherValue = array[index + 1];

                if (value <= otherValue) {
                    min = min(min, value);
                    max = max(max, otherValue);
                } else {
                    min = min(min, otherValue);
                    max = max(max, value);
                }
            }
        }

        return new Point(min, max);
    }

    /////////////////////////////////////////////////////////////////////

    private static int[] getPrimes(int n) {
        boolean[] used = new boolean[n];
        used[0] = used[1] = true;

        int size = 0;
        for (int i = 2; i < n; ++i) {
            if (!used[i]) {
                ++size;
                for (int j = 2 * i; j < n; j += i) {
                    used[j] = true;
                }
            }
        }

        int[] primes = new int[size];
        for (int i = 0, cur = 0; i < n; ++i) {
            if (!used[i]) {
                primes[cur++] = i;
            }
        }

        return primes;
    }

    /////////////////////////////////////////////////////////////////////

    private static long lcm(long a, long b) {
        return a / gcd(a, b) * b;
    }

    private static long gcd(long a, long b) {
        return (a == 0 ? b : gcd(b % a, a));
    }

    /////////////////////////////////////////////////////////////////////

    private static class MultiSet<ValueType> {

        public static <ValueType> MultiSet<ValueType> createMultiSet() {
            Map<ValueType, Integer> multiset = new HashMap<>();
            return new MultiSet<>(multiset);
        }

        private final Map<ValueType, Integer> multiset;
        private int size;

        public MultiSet(Map<ValueType, Integer> multiset) {
            this.multiset = multiset;
            this.size = 0;
        }

        public int size() {
            return size;
        }

        public void inc(ValueType value) {
            int count = get(value);
            multiset.put(value, count + 1);

            ++size;
        }

        public void dec(ValueType value) {
            int count = get(value);
            if (count == 0) return;

            if (count == 1) multiset.remove(value);
            else multiset.put(value, count - 1);

            --size;
        }

        public int get(ValueType value) {
            Integer count = multiset.get(value);
            return (count == null ? 0 : count);
        }
    }

    /////////////////////////////////////////////////////////////////////

    private static class IdMap<KeyType> extends HashMap<KeyType, Integer> {

        /**
         *
         */
        private static final long serialVersionUID = -3793737771950984481L;

        public IdMap() {
            super();
        }

        int getId(KeyType key) {
            Integer id = super.get(key);
            if (id == null) {
                super.put(key, id = size());
            }

            return id;
        }
    }

    /////////////////////////////////////////////////////////////////////

    private static int[] castInt(List<Integer> list) {
        int[] array = new int[list.size()];
        for (int i = 0; i < array.length; ++i) {
            array[i] = list.get(i);
        }

        return array;
    }

    private static long[] castLong(List<Long> list) {
        long[] array = new long[list.size()];
        for (int i = 0; i < array.length; ++i) {
            array[i] = list.get(i);
        }

        return array;
    }
}


import java.io.*;
import java.math.*;
import java.util.*;

public class Main{
    FastScanner in;
    PrintWriter out;

    public long mod = 1000000000+7;
    long[] fact;

    public long bin_pow(long d, long step) {
        if (step == 0) return 1;
        if (step == 1) return d % mod;
        long x = bin_pow(d, step/2);
        x = (x * x) % mod;
        if (step % 2 == 1)
            x = (x * d) % mod;
        return x;
    }

    public long bC(int n, int k) {
        long res = fact[n];
        res *= bin_pow(fact[k], mod-2);
        res %= mod;
        res *= bin_pow(fact[n-k], mod-2);
        res %= mod;
        return res;
    }

    public long C(long n, int k) {
        if (n <= k)
            return bC((int)n, k);

        long res = 1;
        for (int p = 0; p < k ; p++) {
            res *= (n-p) % mod;
            res %= mod;
        }

        res *= bin_pow(fact[k], mod-2);
        res %= mod;

        return res;
    }

    public void solve()
    {
        int n = in.nextInt();
        long s = in.nextLong();
        long[] f = new long[n];
        long sum = 0;
        for (int i = 0; i < n; i++) {
            f[i] = in.nextLong();
            sum += f[i];
        }

        fact = new long[n+10];
        fact[0] = 1;
        for (int i = 1; i < n+10; i++) {
            fact[i] = i * fact[i-1];
            fact[i] %= mod;
        }

        long ans = 0;
        long sg;
        for(int mask = 0; mask < (1<<n); mask++) {
            int cnt = 0;
            sum = s;
            for (int i = 0; i < n; i++)
            if ((mask >> i) % 2 == 1)
            {
                cnt++;
                sum -= f[i]+1;
            }

            if (sum < 0) continue;

            if (cnt % 2 == 1)
                sg = -1;
            else
                sg = 1;

            long tmp_ans = 0;

            tmp_ans = C(sum + n - 1, n - 1);

            ans += sg * tmp_ans;
            ans += 2*mod;
            ans %= mod;
        }

        out.println(ans);
    }

    public void run()
    {
        in = new FastScanner();
        out = new PrintWriter(System.out);

        solve();

        out.close();
    }

    public static void main(String[] args) {
        new Main().run();
    }

    class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }
    }
}


import java.util.Scanner;

public class D {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int r = sc.nextInt();
        int v = sc.nextInt();
        for (int i = 0; i < n; i++) {
            int s = sc.nextInt();
            int f = sc.nextInt();
            double d = f - s;
            double p = 2 * Math.PI * r;
            d %= p;
            double min = 0, max = 2 * Math.PI;
            for (int j = 0; j < 100; j++) {
                double mid = (min + max) / 2;
                double dis = (mid + Math.sin(mid)) * r * 2;
                if (dis < d)
                    min = mid;
                else
                    max = mid;
            }
            double t1 = (f - s - d) / v;
            double t2 = (min + max) * r / v;
            System.out.println(t1 + t2);
        }
        sc.close();
    }
}


import java.util.Scanner;

public class D {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int r = sc.nextInt();
        int v = sc.nextInt();
        for (int i = 0; i < n; i++) {
            int s = sc.nextInt();
            int f = sc.nextInt();
            double d = f - s;
            double p = 2 * Math.PI * r;
            d %= p;
            double min = 0, max = 2 * Math.PI;
            for (int j = 0; j < 100; j++) {
                double mid = (min + max) / 2;
                double dis = (mid + Math.sin(mid)) * r * 2;
                if (dis < d)
                    min = mid;
                else
                    max = mid;
            }
            double t1 = (f - s - d) / v;
            double t2 = (min + max) * r / v;
            if ((min + max) / 2 > Math.PI)
                System.out.println(" = " + (min + max) / 2);
            System.out.println(t1 + t2);
        }
        sc.close();
    }
}


import java.util.Scanner;

/**
 *
 * @author sarthak
 */
public class rnd330_D {
    public static void main(String[] args)
    {
        Scanner s=new Scanner(System.in);
        int n=s.nextInt();
        int r=s.nextInt();
        int v=s.nextInt();
        while(n!=0)
        {
            int st=s.nextInt();
            int en=s.nextInt();
            double half_dis=(double)(en-st)/2;

            double st_angle=0;
            double end_angle=Math.PI;
            //dealing for one half
            int cmplete_revolutions=(int)((en-st)/(2*Math.PI*r));
            double left_dis=(double)(en-st- (double)cmplete_revolutions*2*Math.PI*(double)r);
            left_dis=left_dis/2;

            double dis=0.0;double mid_angle=0;

     for(int i=0;i<=100;i++)
            {
                mid_angle=(st_angle+end_angle)/2.0;
                dis=mid_angle*r +(double)r* Math.sin(mid_angle);
                if(dis<left_dis)
                    st_angle=mid_angle;
                else
                    end_angle=mid_angle;

            }
            double ans=(cmplete_revolutions*2*Math.PI*(double)r  +  2*mid_angle*(double)r);
            ans=(double)ans/(double)v;
            System.out.println(ans);

            n--;
        }

    }

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.DecimalFormat;
import java.text.NumberFormat;

public class P595D {
    private static final double TWO_PI = Math.PI * 2;

    private static double newton(double x) {
        double t = x/2;
        double nt = t - (t + Math.sin(t) - x)/(1 + Math.cos(t));
        while (Math.abs(nt-t) >= 1e-7) {
            t = nt;
            nt = t - (t + Math.sin(t) - x)/(1 + Math.cos(t));
        }
        return nt;
    }

    private static double minTime(long d, int r, int v) {
        final double th = d / (double)r;
        final double k = Math.floor(th/TWO_PI);
        final double x = th % TWO_PI;
        final double t = newton(x/2);
        return (2*t + k*TWO_PI) * r / v;
    }

    public static void main(String[] args) throws IOException {
        final NumberFormat formatter = new DecimalFormat("#.#######");

        final BufferedReader in = new BufferedReader(
            new InputStreamReader(System.in));

        String[] s = in.readLine().split(" ");
        final int n = Integer.parseInt(s[0]);
        final int r = Integer.parseInt(s[1]);
        final int v = Integer.parseInt(s[2]);
        for (int i = 0; i<n; i++) {
            s = in.readLine().split(" ");
            final int si = Integer.parseInt(s[0]);
            final int fi = Integer.parseInt(s[1]);
            System.out.println(formatter.format(minTime(fi-si, r, v)));
        }
    }
}


import java.io.IOException;
import java.io.InputStream;
import java.util.NoSuchElementException;

public class Main {
    public void solve() {
	FastScanner scanner = new FastScanner();
	int N = scanner.nextInt();
	final int R = scanner.nextInt();
	final double V = scanner.nextInt();
	final double cycle = 2.0 * Math.PI * R;

	StringBuilder builder = new StringBuilder();
	for (int i = 0; i < N; i++) {
	    int start = scanner.nextInt();
	    int finish = scanner.nextInt();
	    final int L = finish - start;

	    int A = (int) (L / cycle);
	    double rest = L - cycle * A;
	    rest /= 2.0;
	    double theta = 0.0;
	    double low = 0, high = Math.PI;
	    double plow = low, phigh = high;
	    while (low < high) {
		theta = (high + low) / 2.0;
		double x = R * theta + R * Math.sin(theta);
		if (x > rest) {
		    high = theta;
		} else {
		    low = theta;
		}
		if (plow == low && phigh == high) {
		    break;
		}
		plow = low;
		phigh = high;
	    }

	    double dist = cycle * A + R * 2 * theta;
	    dist /= V;
	    builder.append(dist);
	    builder.append("\n");
	}
	System.out.println(builder.toString());
    }

    public static void main(String[] args) {
	new Main().solve();
    }

}

class FastScanner {
    private final InputStream in = System.in;
    private final byte[] buffer = new byte[1024];
    private int ptr = 0;
    private int buflen = 0;

    private boolean hasNextByte() {
	if (ptr < buflen) {
	    return true;
	} else {
	    ptr = 0;
	    try {
		buflen = in.read(buffer);
	    } catch (IOException e) {
		e.printStackTrace();
	    }
	    if (buflen <= 0) {
		return false;
	    }
	}
	return true;
    }

    private int readByte() {
	if (hasNextByte())
	    return buffer[ptr++];
	else
	    return -1;
    }

    private static boolean isPrintableChar(int c) {
	return 33 <= c && c <= 126;
    }

    private void skipUnprintable() {
	while (hasNextByte() && !isPrintableChar(buffer[ptr]))
	    ptr++;
    }

    public boolean hasNext() {
	skipUnprintable();
	return hasNextByte();
    }

    public String next() {
	if (!hasNext())
	    throw new NoSuchElementException();
	StringBuilder sb = new StringBuilder();
	int b = readByte();
	while (isPrintableChar(b)) {
	    sb.appendCodePoint(b);
	    b = readByte();
	}
	return sb.toString();
    }

    public long nextLong() {
	if (!hasNext())
	    throw new NoSuchElementException();
	long n = 0;
	boolean minus = false;
	int b = readByte();
	if (b == '-') {
	    minus = true;
	    b = readByte();
	}
	if (b < '0' || '9' < b) {
	    throw new NumberFormatException();
	}
	while (true) {
	    if ('0' <= b && b <= '9') {
		n *= 10;
		n += b - '0';
	    } else if (b == -1 || !isPrintableChar(b)) {
		return minus ? -n : n;
	    } else {
		throw new NumberFormatException();
	    }
	    b = readByte();
	}
    }

    public int nextInt() {
	return (int) nextLong();

    }
}


import java.util.Scanner;
import java.lang.Math;

public class D {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int r = scanner.nextInt();
        int v = scanner.nextInt();
        for(int i=0; i<n; ++i) {
          int s = scanner.nextInt();
          int f = scanner.nextInt();
          double d = f - s;
          int cycle = (int)(d/(2*Math.PI*r));
          d -= cycle*(2*Math.PI*r);
          System.out.println((cycle*(2*Math.PI*r) + r*D.bs(d, r))/v);
        }
    }

    public static double bs(double d, int r) {
      double l = 0;
      double u = Math.PI * 2;
      double middle=0;
      while(l<u) {
        middle = (l+u)/2;
        double value = D.eval(middle, r);
        if(value < d) {
          l = middle;
        }
        else {
          u = middle;
        }
        if(Math.abs(value-d) < 0.000001) return middle;
      }
      return middle;
    }
    public static double eval(double theta, double r) {
      return r*theta + 2 * r * Math.sin(theta/2);
    }
}


import java.io.*;
import java.util.*;

public class C329D
{

private static StringTokenizer st;

    public static void nextLine(BufferedReader br) throws IOException
    {
        st = new StringTokenizer(br.readLine());
    }

    public static int nextInt()
    {
        return Integer.parseInt(st.nextToken());
    }

    public static String next()
    {
        return st.nextToken();
    }

    public static long nextLong()
    {
        return Long.parseLong(st.nextToken());
    }

    public static double nextDouble()
    {
        return Double.parseDouble(st.nextToken());
    }

    public static void main(String[] args) throws IOException
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        /*
        for (double d = 0; d < 0.0001; d += 0.000001)
        {
            System.out.println(d + " " + test(d));
            System.out.println((Math.PI - d) + " " + test(Math.PI - d));
        }
        */

        nextLine(br);
        int n = nextInt();
        double r = nextInt();
        double v = nextInt();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < n; i++)
        {
            nextLine(br);
            int start = nextInt();
            int finish = nextInt();
            double diff = finish - start;
            double ans = solve(diff, v, r);
            sb.append(String.valueOf(ans) + "\n");
        }
        System.out.println(sb.toString());

    }

    public static double test(double in)
    {
        double left = 0;
        double right = 1;
        double rem = in;
        for (int i = 0; i < 100; i++)
        {
            double mid = (left + right) / 2;
            double temp = Math.PI * mid;
            double k = temp + Math.sin(temp);
            //if (in > 3.14) System.out.println("M" + mid + " " + k);
            if (k > rem)
            {
                right = mid;
            }
            else
            {
                left = mid;
            }
        }
        return (left + right) / 2;
    }

    public static double solve(double d, double v, double r)
    {
        d = d / r;
        v = v / r;
        double circ = 2 * Math.PI;
        double rounds = Math.floor(d / circ);
        double rem = (d - rounds * circ) / 2;
        double left = 0;
        double right = 1;
        for (int i = 0; i < 100; i++)
        {
            double mid = (left + right) / 2;
            double temp = Math.PI * mid;
            double k = temp + Math.sin(temp);
            if (k > rem)
            {
                right = mid;
            }
            else
            {
                left = mid;
            }
        }
        //System.out.println(rounds + " " + rem + " " + left);

        double ans = ((left + rounds) * circ) / v;
        return ans;
    }

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.StringTokenizer;

/*

 */
/**
 *
 * @author Andy Phan
 */
public class d {
    public static void main(String[] args) {
        FS in = new FS(System.in);
        PrintWriter out = new PrintWriter(System.out);

        int n = in.nextInt();
        double r = in.nextInt();
        double v = in.nextInt()/r;

        while(n-->0) {
            double dist = (-in.nextDouble()+in.nextDouble())/r;
            double a = 0;

            for(double pow = 1e9; pow >= 1e-7; pow /= 2) {
                if(v*(a+pow)+2*Math.abs(Math.sin((v*(a+pow))%(2*Math.PI)/2)) <= dist) a += pow;
            }
            System.out.println(a);
        }

        out.close();
    }

    static class FS {

        BufferedReader in;
        StringTokenizer token;

        public FS(InputStream str) {
            in = new BufferedReader(new InputStreamReader(str));
        }

        public String next() {
            if (token == null || !token.hasMoreElements()) {
                try {
                    token = new StringTokenizer(in.readLine());
                } catch (IOException ex) {
                }
                return next();
            }
            return token.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }
    }
}


import java.util.Arrays;
import java.util.Scanner;
import java.util.function.Function;

public class WarriorAndArcher {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner input = new Scanner(System.in);
		int numberOfComp = input.nextInt();
		int radius = input.nextInt();
		int v = input.nextInt();
		int[] compStart = new int[numberOfComp];
		int[] compEnd = new int[numberOfComp];
		for (int a = 0; a < numberOfComp; a++) {
			compStart[a] = input.nextInt();
			compEnd[a] = input.nextInt();
		}
		for (int a = 0; a < numberOfComp; a++) {
			double turnfrac = (compEnd[a] - compStart[a])
					/ (2 * Math.PI * radius);
			int totalTurns = (int) turnfrac;
			double extraDistance = (turnfrac - totalTurns)
					* (2 * Math.PI * radius);
			double x0 = binarySearch((x) -> radius * x + 2 * Math.sin(x/2.0) * radius, 0, 2*Math.PI, extraDistance);
			double totalTurnsAnswer = x0/(2*Math.PI) + totalTurns;
			double fakeDistance = totalTurnsAnswer * 2 * Math.PI * radius;
			double time = fakeDistance/v;
			System.out.println(time);
		}
	}

	static double binarySearch(Function<Double, Double> f, double low,
			double high, double y) {
		while (Math.ulp(low) < (high - low)) {
			double mid = (low + high) / 2.0;
			double midVal = f.apply(mid);

			if (midVal == y) // unlikely, but possible
				return mid;
			else if (midVal < y)
				low = mid;
			else if (midVal > y)
				high = mid;
		}
		return (low + high) / 2.0;
	}

	/* Outputs 10.000000 */

	// System.out.printf("%.6f%n", x0);

}


import java.util.Scanner;

public class D {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int r = sc.nextInt();
        int v = sc.nextInt();
        for (int i = 0; i < n; i++) {
            int s = sc.nextInt();
            int f = sc.nextInt();
            double d = f - s;
            double p = 2 * Math.PI * r;
            d %= p;
            double min = 0, max = Math.PI;
            for (int j = 0; j < 100; j++) {
                double mid = (min + max) / 2;
                double dis = (mid + Math.sin(mid)) * r * 2;
                if (dis < d)
                    min = mid;
                else
                    max = mid;
            }
            double t1 = (f - s - d) / v;
            double t2 = (min + max) * r / v;
            System.out.println(t1 + t2);
        }
        sc.close();
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author cunbidun
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        DPetyaAndColoring solver = new DPetyaAndColoring();
        solver.solve(1, in, out);
        out.close();
    }

    static class DPetyaAndColoring {
        private static final int MOD = (int) 1e9 + 7;
        private int[] fac = new int[1000030];

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();
            int k = in.nextInt();
            if (m == 1) {
                out.println(Op.powMod(k, n, MOD));
                return;
            }
            int ans = 0;
            fac[0] = 1;
            for (int i = 1; i <= 1000010; i++) {
                fac[i] = Op.mulMod(fac[i - 1], i, MOD);
            }
            int[][] C = MathAlgorithm.binomialTable(2010, MOD);
            int[][] f = new int[n + 1][n + 1];
            f[1][1] = 1;
            for (int i = 2; i <= n; i++) {
                for (int j = 1; j <= i; j++) {
                    f[i][j] = Op.addMod(Op.mulMod(f[i - 1][j], j, MOD), f[i - 1][j - 1], MOD);
                }
            }
            for (int j = 0; j <= n; j++) {
                for (int i = j; i <= n; i++)
                    if (2 * i - j <= k) {
                        int tmp = C(k, 2 * i - j);
                        tmp = Op.mulMod(tmp, C[2 * i - j][i - j], MOD);
                        tmp = Op.mulMod(tmp, C[i][i - j], MOD);
                        tmp = Op.mulMod(tmp, fac[i], MOD);
                        tmp = Op.mulMod(tmp, fac[i], MOD);
                        tmp = Op.mulMod(tmp, f[n][i], MOD);
                        tmp = Op.mulMod(tmp, f[n][i], MOD);
                        tmp = Op.mulMod(tmp, Op.powMod(j, n * (m - 2), MOD), MOD);
                        ans = Op.addMod(tmp, ans, MOD);
                    }
            }
            out.println(ans);
        }

        private int C(int n, int k) {
            return Op.mulMod(Op.mulMod(fac[n], Op.inv(fac[k], MOD), MOD), Op.inv(fac[n - k], MOD), MOD);
        }

    }

    static class Op {
        public static int addMod(int x, int y, int MOD) {
            return ((x + y) >= MOD ? x + y - MOD : x + y);
        }

        public static int mulMod(int x, int y, int MOD) {
            return (int) (((long) x * y) % MOD);
        }

        public static int powMod(int x, long p, int MOD) {
            if (p == 0) return 1;
            int t = powMod(x, p / 2, MOD);
            if ((p & 1) == 1)
                return mulMod(mulMod(t, t, MOD), x, MOD);
            return mulMod(t, t, MOD);
        }

        public static int inv(int x, int MOD) {
            return powMod(x, MOD - 2, MOD);
        }

    }

    static class MathAlgorithm {
        public static int[][] binomialTable(int n, int MOD) {
            int[][] c = new int[n + 1][n + 1];
            for (int i = 0; i <= n; i++)
                for (int j = 0; j <= i; j++)
                    c[i][j] = (j == 0) ? 1 : Op.addMod(c[i - 1][j - 1], c[i - 1][j], MOD);
            return c;
        }

    }

    static class InputReader extends InputStream {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        private static boolean isSpaceChar(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

    }
}