There are r red and g green blocks for construction of the red-green tower. Red-green tower can be built following next rules:  Red-green tower is consisting of some number of levels;  Let the red-green tower consist of n levels, then the first level of this tower should consist of n blocks, second level — of n - 1 blocks, the third one — of n - 2 blocks, and so on — the last level of such tower should consist of the one block. In other words, each successive level should contain one block less than the previous one;  Each level of the red-green tower should contain blocks of the same color.  Let h be the maximum possible number of levels of red-green tower, that can be built out of r red and g green blocks meeting the rules above. The task is to determine how many different red-green towers having h levels can be built out of the available blocks.Two red-green towers are considered different if there exists some level, that consists of red blocks in the one tower and consists of green blocks in the other tower.You are to write a program that will find the number of different red-green towers of height h modulo 109 + 7.

The only line of input contains two integers r and g, separated by a single space — the number of available red and green blocks respectively (0 ≤ r, g ≤ 2·105, r + g ≥ 1).

Output the only integer — the number of different possible red-green towers of height h modulo 109 + 7.

NoteThe image in the problem statement shows all possible red-green towers for the first sample.

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author Rustam Musin (PloadyFree@gmail.com)
 */
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);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        private int mod = (int) (1e9 + 7);

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            int red = in.readInt();
            int green = in.readInt();
            int maxH = 1;
            while (sum(maxH + 1) <= red + green) {
                maxH++;
            }
            int totalCubes = sum(maxH);

            int[][] dp = new int[2][red + 1];
            for (int redUsed = 0; redUsed <= red; redUsed++) {
                int greenUsed = totalCubes - redUsed;
                if (greenUsed <= green && redUsed <= totalCubes) {
                    dp[maxH & 1][redUsed] = 1;
                }
            }
            for (int h = maxH - 1; h >= 0; h--) {
                for (int redUsed = 0; redUsed <= red; redUsed++) {
                    dp[h & 1][redUsed] = 0;
                    int greenUsed = sum(h) - redUsed;
                    if (greenUsed <= green && redUsed <= sum(h)) {
                        if (redUsed + h + 1 <= red) {
                            dp[h & 1][redUsed] += dp[(h & 1) ^ 1][redUsed + h + 1];
                        }
                        if (greenUsed + h + 1 <= green) {
                            dp[h & 1][redUsed] += dp[(h & 1) ^ 1][redUsed];
                        }
                        dp[h & 1][redUsed] %= mod;
                    }
                }
            }
            out.print(dp[0][0]);
        }

        private int sum(int x) {
            return x * (x + 1) / 2;
        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.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 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);

        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

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

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

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

        public void print(int i) {
            writer.print(i);
        }

    }
}

import java.util.*;
import java.io.*;
import static java.lang.Math.*;

public class PracticeProblem
{
    public static FastReader in = new FastReader();
    public static PrintWriter out = new PrintWriter(System.out);
    public static final int MOD = (int)1e9 + 7;

    public static void main(String[] args)
    {
        int r = in.nextInt(), g = in.nextInt();
        int n = levels(r + g);

        long[] dp = new long[r + 1];
        Arrays.fill(dp, 1);

        int blocksUsed = n * (n + 1) / 2;

        for (int level = 1; level <= n; level++)
        {
            blocksUsed -= level;

            for (int redUsed = 0; redUsed <= min(blocksUsed, r); redUsed++)
            {
                long answer = 0;
                int redLeft = r - redUsed;
                int greenLeft = g - (blocksUsed - redUsed);
                if (redLeft >= level)
                    answer += dp[redUsed + level];
                if (greenLeft >= level)
                    answer += dp[redUsed];

                dp[redUsed] = answer % MOD;
            }
        }

        out.println(dp[0]);
        out.close();
    }

    private static int levels(int blocks)
    {
        int answer = 1;

        while (answer * (answer + 1) / 2 <= blocks)
            answer++;

        return --answer;
    }

    /*
     * This FastReader code is taken from GeeksForGeeks.com
     * https://www.geeksforgeeks.org/fast-io-in-java-in-competitive-programming/
     *
     * The article was written by Rishabh Mahrsee
     */
    public static class FastReader
    {
        BufferedReader br;
        StringTokenizer st;

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

        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                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());
        }

        String nextLine()
        {
            String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
        }
    }
}

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

public class Solution {

    static MyScanner sc;
    private static PrintWriter out;
    static long M2 = 1_000_000_000L + 7;

    private static HashMap<Long, Long>[] mods;

    public static void main(String[] s) throws Exception {
        StringBuilder stringBuilder = new StringBuilder();

        if (stringBuilder.length() == 0) {
            sc = new MyScanner(System.in);
        } else {
            sc = new MyScanner(new BufferedReader(new StringReader(stringBuilder.toString())));
        }

        out = new PrintWriter(new OutputStreamWriter(System.out));

        initData();
        solve();
        out.flush();
    }

    private static void initData() {

    }

    static String k;
    static long[] t0;
    static long[] t1;

    static long[] pow0;
    static long[] pow1;

    private static void solve() {
        int n = sc.nextInt();
        int a = sc.nextInt();
        int rt = 0;
        for (int l = 1; l < 1000; l++) {
            if (l * (l + 1) / 2 <= a + n) {
                rt = l;
            } else break;
        }
        int mm = Math.min(n, a);
        if (mm <= 1) {
            out.println(mm + 1);
            return;
        }

        int total = rt * (rt + 1) / 2;
        int min = Math.max(0, total - Math.max(a, n));

        int e = Math.min(total, mm);
        int[] res = new int[e + 1];
        res[0] = 1;
        res[1] = 1;
        int lastz = 1;
        for (int i = 1; i < rt; i++) {
            for (int l = Math.min(e - i - 1, lastz); l >= 0; l--) {
                res[l + i + 1] += res[l];
                res[l + i + 1] %= M2;
                lastz = Math.max(lastz, l + i + 1);
            }
        }
        long resr = 0;
        for (int k = min; k <= e; k++) {
            resr += res[k];
            resr %= M2;
        }
        out.println(resr);
    }

    private static boolean solve(int n, int p, int p1, int i) {
        return false;
    }

    private static boolean isset(long i, int k) {
        return (i & (1 << k)) > 0;
    }

    private static void solveT() throws IOException {
        int t = sc.nextInt();
        while (t-- > 0) {
            solve();
        }
    }

    private static long gcd(long l, long l1) {
        if (l > l1) return gcd(l1, l);
        if (l == 0) return l1;
        return gcd(l1 % l, l);
    }

    private static long pow(long a, long b, long m) {
        if (b == 0) return 1;
        if (b == 1) return a;
        long pp = pow(a, b / 2, m);
        pp *= pp;
        pp %= m;
        return (pp * (b % 2 == 0 ? 1 : a)) % m;
    }

    static class MyScanner {
        BufferedReader br;
        StringTokenizer st;

        MyScanner(BufferedReader br) {
            this.br = br;
        }

        public MyScanner(InputStream in) {
            this(new BufferedReader(new InputStreamReader(in)));
        }

        void findToken() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }

        String next() {
            findToken();
            return st.nextToken();
        }

        Integer[] nab(int n) {
            Integer[] k = new Integer[n];
            for (int i = 0; i < n; i++) {
                k[i] = sc.fi();
            }
            return k;
        }

        int[] na(int n) {
            int[] k = new int[n];
            for (int i = 0; i < n; i++) {
                k[i] = sc.fi();
            }
            return k;
        }

        long[] nl(int n) {
            long[] k = new long[n];
            for (int i = 0; i < n; i++) {
                k[i] = sc.nextLong();
            }
            return k;
        }

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

        int fi() {
            String t = next();
            int cur = 0;
            boolean n = t.charAt(0) == '-';
            for (int a = n ? 1 : 0; a < t.length(); a++) {
                cur = cur * 10 + t.charAt(a) - '0';
            }
            return n ? -cur : cur;
        }

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

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

}

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

public class D_RedGreenTowers {

	static int M = (int) (2 * Math.pow(10, 5)) + 1, N = 633;
	static int mod = (int) (1e9 + 7);
	static int R, G, H;
	static int dp[][] = new int[2][M];

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

		R = sc.nextInt(); G = sc.nextInt();
		int total = R + G;
		H = 1; total -= 1;
		int i = 2;
		while(total >= i) {
			total -= i;
			i++; H++;
		}
		out.println(solve());

		out.flush();
		out.close();
	}

//	private static int solve(int level, int r, int g) {
//		if(level == H + 1) return 1;
//		if(r < level && g < level) return 0;
//		if(memo[level][r] != -1) return memo[level][r];
//
//		int ways = 0;
//		if(g >= level)
//			ways += solve(level + 1, r, g - level);
//		if(r >= level)
//			ways += solve(level + 1, r - level, g);
//		return memo[level][r] = ways % mod;
//	}

	private static int blocks(int level) {
		return (level * (level + 1)) / 2;
	}

	private static int solve() {
		dp[0][R] = 1; int total = R + G;
		int curr = 0;
		for(int i = 0; i < H; ++i) {
			for(int reds = R; reds >= 0; reds--) {
				int greens = total - blocks(i) - reds;
				if(dp[curr][reds] != 0) {
					if(reds >= (i + 1))
						dp[1 - curr][reds - (i + 1)] = (dp[1 - curr][reds - (i + 1)] + dp[curr][reds]) % mod;
					if(greens >= (i + 1)) dp[1 - curr][reds] = (dp[curr][reds] + dp[1 - curr][reds]) % mod;
				}
				dp[curr][reds] = 0;
			}
			curr = 1 - curr;
		}
		int res = 0;
		for(int i = 0; i <= R; ++i) res = (dp[curr][i] + res) % mod;
		return res;
	}

	static class Scanner{
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}

		public Scanner(FileReader r){	br = new BufferedReader(r);}

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

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

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

		public String nextLine() throws IOException {return br.readLine();}

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

		public boolean ready() throws IOException {return br.ready();}
	}
}

import java.util.Scanner;
import java.io.PrintWriter;

public class d {
	private static final int maxh = 1000;
	private static final long mod = 1000000000 + 7;
	private static int sumx(int k){
		int l = 0;
		int r = maxh;
		while (r - l > 1){
			int m = (r + l) >> 1;
			if (m * (m + 1) > 2 * k)
				r = m;
			else if (m * (m + 1) < 2 * k)
				l = m;
			else
				return m;
		}
		return l;
	}
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		PrintWriter out = new PrintWriter(System.out);
		int r = 0, g = 0;
		r = in.nextInt();
		g = in.nextInt();
		if (r < g){
			int t = r;
			r = g;
			g = t;
		}
		int h = sumx(r + g);
		int dp[][] = new int[2][r + 1];
		for (int i = 0; i < r + 1; i++)
			dp[0][i] = 0;
		dp[0][0] = dp[0][1] = 1;
		int cur = 1;
		for (int i = 1; i < h; i++){
			for (int j = 0; j <= i; j++)
				dp[cur][j] = dp[cur ^ 1][j];
			for (int j = i + 1; j <= r; j++){
				dp[cur][j] = dp[cur ^ 1][j - i - 1] + dp[cur ^ 1][j];
				if (dp[cur][j] >= mod)
					dp[cur][j] -= mod;
			}
			cur = cur ^ 1;
		}
		long ans = 0;
		for (int i = Math.max(0, h * (h + 1) / 2 - g); i <= r; i++){
			ans += (long)dp[cur ^ 1][i];
		}
		ans %= mod;
		out.println(ans);
		in.close();
		out.close();
	}
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class D {

	static class Scanner{
		BufferedReader br=null;
		StringTokenizer tk=null;
		public Scanner(){
			br=new BufferedReader(new InputStreamReader(System.in));
		}
		public String next() throws IOException{
			while(tk==null || !tk.hasMoreTokens())
				tk=new StringTokenizer(br.readLine());
			return tk.nextToken();
		}
		public int nextInt() throws NumberFormatException, IOException{
			return Integer.valueOf(next());
		}
		public long nextLong() throws NumberFormatException, IOException{
			return Long.valueOf(next());
		}
		public double nextDouble() throws NumberFormatException, IOException{
			return Double.valueOf(next());
		}
	}

	static int R, G;
	static int mod = 1000000007;
	static int[][] dp;

	static int gastado(int level){
		int ret = level * (level + 1);
		return ret/2;
	}

	static int getlevel(){
		int maxlevel = 0;
		while(gastado(maxlevel) <= R + G)
			maxlevel++;
		return maxlevel - 1;
	}

	public static void main(String args[]) throws NumberFormatException, IOException{
		Scanner sc = new Scanner();
		R = sc.nextInt();
		G = sc.nextInt();
		dp = new int[2][R + 1];
		int h = getlevel();
		for(int i = 0; i <= R; i++)
			dp[h & 1][i] = 1;
		for(int i = h - 1; i >= 0; i--){
			for(int r = 0; r <= Math.min(R, gastado(i)); r++){
				int quedarojo = R - r;
				int quedaverde = G - (gastado(i) - r);
				if (quedaverde < 0)
					continue;
				int current = i + 1;
				dp[i & 1][r] = 0;
				if (quedarojo >= current)
					dp[i & 1][r] = dp[(i + 1)&1][r + current];
				if (quedaverde >= current)
					dp[i & 1][r] = (dp[i & 1][r] +  dp[(i + 1)&1][r]) % mod;
				//System.out.print(i +" " + r + "," + dp[i % 2][r] + " - ");
			}
			//System.out.println();
		}
		System.out.println(dp[0][0]);
	}
}

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

public class C {
	static int mod = (int)1e9+7;
	public static void main(String[] args) throws NumberFormatException, IOException {
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);
		int r = sc.nextInt(), g = sc.nextInt();
		int h = 1, sum = 1;
		while(sum <= r+g){
			sum += ++h;
		}
		int [][] dp = new int[2][r+1];
		Arrays.fill(dp[h%2], 1);
		int tot = h * (h-1) / 2;
		for (int i = h-1, cur = i%2; i > 0; --i, cur ^= 1) {
			tot -= i;
			for (int j = 0; j < dp[cur].length; ++j) {
				dp[cur][j] = 0;
				if(j - i >= 0)
					dp[cur][j] = dp[1^cur][j - i];
				//rem green blocks in level i
				int gg = g - (tot - (r-j));
				if(gg >= i)
					dp[cur][j] += dp[1^cur][j];
				if(dp[cur][j] >= mod)
					dp[cur][j] -= mod;
				}
		}
		out.println(dp[1][r]);
		out.close();
	}

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

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

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

		public int nextInt() throws NumberFormatException, IOException {
			return Integer.parseInt(next());
		}
	}

}

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

public class RedGreenTower implements Closeable {

  private InputReader in = new InputReader(System.in);
  private PrintWriter out = new PrintWriter(System.out);

  public void solve() {
    R = in.ni();
    G = in.ni();
    maxHeight();
    out.println(dp());
  }

  private int R, G, H, tower;

  private void maxHeight() {
    int height = 1, total = R + G;
    while (height * (height + 1) <= 2 * total) {
      height++;
    }
    H = height - 1;
    tower = H * (H + 1) / 2;
  }

  private int dp() {
    int[] prev = new int[R + 1];
    for (int red = 0; red <= R; red++) {
      int redUsed = R - red;
      int green = tower - redUsed;
      if (green <= G) {
        prev[red] = 1;
      }
    }
    final int MOD = (int) 1e9 + 7;
    for (int row = 1; row <= H; row++) {
      int[] current = new int[R + 1];
      for (int red = 0; red <= R; red++) {
        if (row <= red) {
          current[red] += prev[red - row];
          current[red] %= MOD;
        }
        current[red] += prev[red];
        current[red] %= MOD;
      }
      prev = current;
    }
    return prev[R];
  }

  @Override
  public void close() throws IOException {
    in.close();
    out.close();
  }

  static class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;

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

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

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

    public long nl() {
      return Long.parseLong(next());
    }

    public void close() throws IOException {
      reader.close();
    }
  }

  public static void main(String[] args) throws IOException {
    try (RedGreenTower instance = new RedGreenTower()) {
      instance.solve();
    }
  }
}

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

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);
        TaskD solver = new TaskD();
        solver.solve(in, out);
        out.close();
    }
}

class TaskD {

    private int MAXN = 200000;

    private long DP[] = new long[MAXN+1];

    private long MOD = (long) (1e9 + 7);

    void solve(InputReader in, OutputWriter out) {
        int red = in.nextInt();
        int green = in.nextInt();

        int height = getMaxHeight(red, green);

        DP[0] = 1;

        int numberOfBlocks = getNumberOfBlocks(height);
        for (int h = 1; h <= height; h++) {
            for (int r = Math.min(red, numberOfBlocks); r >= h; r--) {
                DP[r] += DP[r - h];
                if (DP[r] >= MOD) DP[r] -= MOD;
            }
        }
        long result = 0;
        for (int r = 0; r <= red; r++) {
            if (numberOfBlocks - r <= green) {
                result += DP[r];
                if (result >= MOD) result -= MOD;
            }
        }
        out.printLine(result);
    }

    private int getMaxHeight(int red, int green) {
        int h = 1;
        while(true) {
            if(red + green < getNumberOfBlocks(h)) break;
            h++;
        }
        return (h-1);
    }

    private int getNumberOfBlocks(int height) {
        return ((height) * (height + 1)) / 2;
    }

}
class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;
    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream), 32768);
        tokenizer = null;
    }
    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }
    public boolean hasNext() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                String line = reader.readLine();
                if ( line == null ) {
                    return false;
                }
                tokenizer = new StringTokenizer(line);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return true;
    }
    public int nextInt() {
        return Integer.parseInt(next());
    }
    public long nextLong() {
        return Long.parseLong(next());
    }
    public double nextDouble() { return Double.parseDouble(next());}
}
class OutputWriter {
    private final PrintWriter writer;
    public OutputWriter(OutputStream outputStream) {
        writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
    }
    public OutputWriter(Writer writer) {
        this.writer = new PrintWriter(writer);
    }
    public void print(Object... objects) {
        for (int i = 0; i < objects.length; i++) {
            if ( i != 0 ) {
                writer.print(' ');
            }
            writer.print(objects[i]);
        }
    }
    public void printLine(Object... objects) {
        print(objects);
        writer.println();
    }
    public void close() {
        writer.close();
    }
}

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.StringTokenizer;

public class R273D2D {
    static int totalBlock, maxH;
    static int[] dp;
    static final int MOD = (int)1e9+7;
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int rr = Integer.parseInt(st.nextToken());
        int gg = Integer.parseInt(st.nextToken());
        maxH=1;
        while(maxH*(maxH+1)/2<=rr+gg){
            maxH++;
        }
        maxH--;
        totalBlock = rr+gg;
        dp = new int[rr+1];
        for(int h=0; h<=maxH; h++){
            int[] tmp = new int[rr+1];
            for(int r=0; r<=rr; r++){
                int g = (totalBlock-(maxH-h)*(maxH+h+1)/2) - r;
                if(g<0) continue;
                if(r==0 || g==0 || h==0) tmp[r]=1; else{
                    if(r>=h) tmp[r] = (tmp[r]+dp[r-h])%MOD;
                    if(g>=h) tmp[r] = (tmp[r]+dp[r])%MOD;
                }
            }
            dp = tmp;
        }
        System.out.println(dp[rr]);
    }
}

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.PrintWriter;
import java.util.Scanner;
import java.lang.Math.*;

public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner cin = new Scanner(new BufferedInputStream(System.in));
        PrintWriter cout = new PrintWriter(new BufferedOutputStream(System.out));
        Task work = new Task(cin, cout);
        work.solve();
        cout.flush();
    }

}
class Task{
    Scanner cin;
    PrintWriter cout;
    final int maxn = 400005;
    final int MOD = 1000000007;
    int []dp = new int[maxn];
    int r, g;
    public Task(Scanner cin, PrintWriter cout) {
        // TODO Auto-generated constructor stub
        this.cin = cin;
        this.cout = cout;
        r = cin.nextInt();
        g = cin.nextInt();
    }
    public void read() {
        r = cin.nextInt();
        g = cin.nextInt();
    }
    int GetHeight(){
        for (int i = 1; ; i++){
            if (i * (i + 1) / 2 > r + g){
                return i-1;
            }
        }
    }
    public void solve(){
        int h = GetHeight();
        int res = 0;
        dp[0] = 1;
        for (int i = 1; i <= h; i++){
            for (int j = r; j >= 0; j--){
                dp[i+j] = (dp[i+j] + dp[j]) % MOD;
            }
        }
        for (int i = Math.max(h*(h+1)/2 - g, 0); i <= r; i++){
            res = (res + dp[i]) % MOD;
        }
        cout.println(res);
    }
}

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

import static java.lang.Math.*;
import static java.util.Arrays.*;
import static java.util.Collections.*;

public class Main{

	// ArrayList<Integer> lis = new ArrayList<Integer>();
	// ArrayList<String> lis = new ArrayList<String>();
	//  PriorityQueue<P> que = new PriorityQueue<P>();
	// PriorityQueue<Integer> que = new PriorityQueue<Integer>();
	//  Stack<Integer> que = new Stack<Integer>();
	//HashMap<Long,Long> map = new HashMap<Long,Long>();
    //	static long sum=0;
	// 1000000007 (10^9+7)
	static int mod = 1000000007;
	//static int mod = 1000000009,r=0; ArrayList<Integer> l[]= new ArrayList[n];
   // static int dx[]={1,-1,0,0};
//	static int dy[]={0,0,1,-1};
//	static int dx[]={1,-1,0,0,1,1,-1,-1};
//  static int dy[]={0,0,1,-1,1,-1,1,-1};
	//static Set<Integer> set = new HashSet<Integer>();

	//static ArrayList<Integer> l[];
    //static int parent[][],depth[],node,max_log;

public  static void main(String[] args)   throws Exception, IOException{
   //String line=""; throws Exception, IOException
   //(line=br.readLine())!=null
	//Scanner sc =new Scanner(System.in);
	// !!caution!! int long //
	Reader sc = new Reader(System.in);

    //,a=sc.nextInt(),b=sc.nextInt();
 	// int n=sc.nextInt(),p[]=new int[n],q[]=new int[n];
	//int n=sc.nextInt(),a[]=new int[n],b[]=new int[n];
	//int n=sc.nextInt(); //,k=sc.nextInt();
	//long n=sc.nextLong(),k=0,r=0;

	//int n=sc.nextInt(), e[][]=new int[n][n];

	int r=sc.nextInt(), g=sc.nextInt();
	int h=(int)sqrt( 2*(r+g) ), m=min(r,g);

	if( (long)h*(h+1)/2>r+g )h--;

	long d[][]=new long[2][m+1];
    long a=0;

   // d[1][1]++;
    d[0][0]=d[1][0]=1;

	for (int i = 1; i <= h ; i++) {

		int c=i%2,cc=(c+1)%2;
		long x=(long)i*(i+1);

     for (int j = 1; j<=m && x>=j ; j++) {
    	 if( j<i ){  d[c][j]=d[cc][j]; continue;}
    	   d[c][j]=d[cc][j]+d[cc][j-i];
    	   d[c][j]%=mod;
	    }
    // db(i,d);

	}

	long df=-(long)h*(h+1)/2+r+g;
	//  db(h);

	for (int i = 0; i <= df && m-i>=0 ; i++){
		a+=d[h%2][m-i];
		a%=mod;
	}

	System.out.println( a );

}

/*
  static class P implements Comparable<P>{
	int id, d; ;
	P(int id,int d){
		this.id=id;
		this.d=d;
	}

	public int compareTo(P x){
	//	return  (-x.d+d)>=0?1:-1  ; // ascend long
		return   -x.d+d  ; // ascend
	//	 return   x.d-d  ; //descend
	   }

}
*/

static void db(Object... os){
    System.err.println(Arrays.deepToString(os));

}

}

class QuickUnionWeighted {
    public int[] id;
    private int[] sz;
    public QuickUnionWeighted(int N)
    {
        id = new int[N];
        sz = new int[N];
        for (int i = 0; i < N; i++) {
            id[i] = i;
            sz[i] = 1;
        }
    }

    private int root(int p) {
        while (id[p] != p) p = id[p];
        return p;
    }

    public boolean connected(int id1, int id2) {
        return root(id1) == root(id2);
    }

    public void union(int p, int q) {
        int i = root(p);
        int j = root(q);
        if( i==j )return;
        if (sz[i] < sz[j]) { id[i] = j; sz[j] += sz[i];   }
        else               { id[j] = i; sz[i] += sz[j];   }
    }
    public int sz(int x){
   	 return sz[ root(x) ];
    }
 }

class Reader
{
	private BufferedReader x;
	private StringTokenizer st;

	public Reader(InputStream in)
	{
		x = new BufferedReader(new InputStreamReader(in));
		st = null;
	}
	public String nextString() throws IOException
	{
		while( st==null || !st.hasMoreTokens() )
			st = new StringTokenizer(x.readLine());
		return st.nextToken();
	}
	public int nextInt() throws IOException
	{
		return Integer.parseInt(nextString());
	}
	public long nextLong() throws IOException
	{
		return Long.parseLong(nextString());
	}
	public double nextDouble() throws IOException
	{
		return Double.parseDouble(nextString());
	}
}

import java.util.Scanner;

public class D {
    public static final int MOD = 1000000007;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int r = sc.nextInt();
        int g = sc.nextInt();
        System.out.println(solve(r, g));
    }

    private static int solve(int r, int g) {
        if (r < g) {
            return solve(g, r);
        }
        int h = maxHeight(r + g);
        int[] a = new int[g + 1];
        a[0] = 1;
        for (int i = 1; i <= h; i++) {
            for (int j = g - i; j >= 0; j--) {
                a[i + j] = (a[i + j] + a[j]) % MOD;
            }
        }

        int res = 0;
        int blocks = h*(h+1)/2;
        for (int i = 0; i <= g; i++) {
            res = (res + (blocks - i <= r ? a[i] : 0)) % MOD;
        }
        return res;
    }

    private static int maxHeight(int blocks) {
        int c = blocks << 1;
        int d = (int)Math.sqrt(1 + 4 * c);
        int h = (d - 1) / 2;
        return h;
    }

}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

public class D {
     int r;
     int g;
     int dp [][];

    BufferedReader br;
    StringTokenizer in;
    PrintWriter out;

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

        return in.nextToken();
    }

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

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

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

    public void solve() throws IOException {
        br = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(System.out);

        r = nextInt();
        g = nextInt();

        if(g < r) {
            int a = g;
            g = r;
            r = a;
        }

        dp = new int[2][r+1];
        if(r > 0)
            dp[0][1] = 1;
        if(g > 0)
            dp[0][0] = 1;

        for(int h = 2; h <= 900 ; h++) {
            boolean update = false;
            for(int red = dp[0].length-1 ; red >= 0; red--) {
                int green = (h * (h-1)) / 2 - red;
                if(red - h >= 0 && dp[0][red-h] > 0) {
                    dp[1][red] = dp[0][red-h];
                    update = true;
                } else {
                    dp[1][red] = 0;
                }

                if(green+h <= g) {
                    dp[1][red] += dp[0][red];
                    if(dp[1][red] >= 1000000007)
                        dp[1][red] -= 1000000007;
                    update = true;
                }
            }
            if(!update) {
                break;
            } else {
                int [] val = dp[0];
                dp[0] = dp[1];
                dp[1] = val;
            }
        }
        int result = 0;
        for(int i = 0 ; i < dp[0].length; i++) {
            result += dp[0][i];
            if(result >= 1000000007)
                result -= 1000000007;
        }
        out.println(result%1000000007);
        out.close();
    }
    public static void main (String [] args) throws IOException {
        new D().solve();
    }
}

import java.util.*;
import java.io.*;
public class RedGreenTowers {

    /************************ SOLUTION STARTS HERE ************************/

    static final int mod = (int) 1e9 + 7;

    private static void solve() {

        int R = nextInt();
        int G = nextInt();

        int DPprev[] = new int[R + 1];  // number of ways of building blocks using exactly i red blocks
        DPprev[0] = G > 0 ? 1 : 0;

        if(R > 0)
            DPprev[1] = 1;

        boolean flag = false;
        int h = 2;
        int hMax = (int) Math.ceil((Math.sqrt(1 + 8 * (R + G)) - 1) / 2.0) + 1;
        for(int run = 1; run <= hMax; run++) {
            int DPnew[] = new int[R + 1];
            flag = false;
            for(int i = 0; i <= R; i++) {
                int j = ((h * (h + 1)) / 2) - i;    // green
                if(i >= h) {    // build base with red
                    DPnew[i] = DPprev[i - h];
                }
                if(j >= h && j <= G) {    // build base with green
                    DPnew[i] = (DPnew[i] + DPprev[i]) % mod;
                }

                flag |= DPnew[i] != 0;
            }

            if(!flag)
                break;

            DPprev = DPnew;
            h++;

        }
        int sum = 0;
        for(int a : DPprev)
            sum = (sum + a) % mod;

        println(sum);

    }

    /************************ SOLUTION ENDS HERE ************************/

    /************************ TEMPLATE STARTS HERE **********************/

    public static void main(String[] args) throws IOException {
        reader = new BufferedReader(new InputStreamReader(System.in));
        writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)), false);
        st     = null;
        solve();
        reader.close();
        writer.close();
    }

    static BufferedReader reader;
    static PrintWriter    writer;
    static StringTokenizer st;

    static String next()
    {while(st == null || !st.hasMoreTokens()){try{String line = reader.readLine();if(line == null){return null;}
    st = new StringTokenizer(line);}catch (Exception e){throw new RuntimeException();}}return st.nextToken();}
    static String nextLine()  {String s=null;try{s=reader.readLine();}catch(IOException e){e.printStackTrace();}return s;}
    static int    nextInt()   {return Integer.parseInt(next());}
    static long   nextLong()  {return Long.parseLong(next());}
    static double nextDouble(){return Double.parseDouble(next());}
    static char   nextChar()  {return next().charAt(0);}
    static int[]  nextIntArray(int n)         {int[] a= new int[n];   int i=0;while(i<n){a[i++]=nextInt();}  return a;}
    static long[] nextLongArray(int n)        {long[]a= new long[n];  int i=0;while(i<n){a[i++]=nextLong();} return a;}
    static int[]  nextIntArrayOneBased(int n) {int[] a= new int[n+1]; int i=1;while(i<=n){a[i++]=nextInt();} return a;}
    static long[] nextLongArrayOneBased(int n){long[]a= new long[n+1];int i=1;while(i<=n){a[i++]=nextLong();}return a;}
    static void   print(Object o)  { writer.print(o);  }
    static void   println(Object o){ writer.println(o);}

    /************************ TEMPLATE ENDS HERE ************************/

}

/* package whatever; // don't place package name! */

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

/* Name of the class has to be "Main" only if the class is public. */
public class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        Scanner sc = new Scanner(System.in);
        int mod = 1000000007;
        int r = sc.nextInt();
        int g = sc.nextInt();
        int n = (int)Math.floor((Math.pow(8*(r+g)+1, 0.5)-1)/2);
        int firstdp[] = new int[n*(n+1)/2+1];
        int seconddp[] = new int[n*(n+1)/2+1];
        int temp[] = new int[n*(n+1)/2+1];
        for(int i = 0;i<=n*(n+1)/2;i++){
            firstdp[i]=0;
            seconddp[i]=0;
        }
        firstdp[0]=1;
        for(int i = 1;i<n+1;i++){
            for(int j = 0;j<i;j++){
                seconddp[j]=firstdp[j]%mod;
                temp[j]=seconddp[j];
            }
            for(int j = i;j<=i*(i+1)/2;j++){
                seconddp[j]=(firstdp[j]%mod+firstdp[j-i]%mod)%mod;
                temp[j]=seconddp[j];
            }
            for(int j = 0;j<=i*(i+1)/2;j++){
                firstdp[j]=temp[j];
            }

        /*for(int j = 0;j<=(n*(n+1))/2;j++){
                System.out.print(firstdp[j]);
            }
            System.out.println();
        for(int j = 0;j<=(n*(n+1))/2;j++){
                System.out.print(seconddp[j]);
            }
            System.out.println();*/
        }
        if(r>n*(n+1)/2){
            r=n*(n+1)/2;
        }
        if(g>n*(n+1)/2){
            g=n*(n+1)/2;
        }
        int lower = Math.max(0,n*(n+1)/2-g);
        int upper = Math.min(r,n*(n+1)/2);
        long answer = 0;
        for(int i = lower;i<=upper;i++){
            answer+=(long)(seconddp[i]%(long)mod);
            answer=answer%mod;
        }
        System.out.println(answer);
        /*System.out.println("=============");
        System.out.println(lower + " " + upper);
        System.out.println("=============");
        System.out.println(n);*/
    }
}

//package codeforces;

import java.util.Scanner;

/**
 * Created by nitin.s on 06/03/16.
 */
public class RedGreenTowers {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int r = in.nextInt();
        int g = in.nextInt();
        int h = 1;
        for(; h * (h + 1)/2 <= r+g; ++h);
        --h;
        int[] dp = new int[r + 1];
        dp[0] = 1;
        int mod = 1000000007;
        long ret = 0;
        for(int i = 1; i <= h; ++i) {
            for(int j = r - i; j >= 0; --j) {
                dp[j + i] += dp[j];
                if(dp[j + i] >= mod) {
                    dp[j + i] -= mod;
                }
            }
        }
        for(int j = 0; j <= r; ++j) {
            if(h * (h + 1) / 2 - j <= g) {
                ret += dp[j];
            }
        }
        System.out.println(ret % mod);
    }
}

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;
import java.util.Stack;
import java.util.StringTokenizer;

public class Main {
	static boolean can (int r , int g , int h) {
		while (h > 0 && (r > 0 || g > 0) && (r >= h || g >= h)) {
			if (r < g) {
				if (r >= h)
					r -= h;
				else g -= h;
			}

			else if (g >= h)
				g -= h;
			else r -= h;
			h -- ;
		}
		return h <= 0;
	}
	static int getH (int r , int g) {
		int lo = 0 ;
		int hi = (int)1e5;
		int max = 0;
		for(int i = 0 ; i < 20 ; ++i) {
			int mid = lo + ((hi - lo) >> 1);
			if (can(r , g , mid)) {
				max = Math.max(max, mid);
				lo = mid + 1;
			}
			else hi = mid - 1 ;
		}
		return max;
	}

	public static void main(String[] args) throws Exception {
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(bf.readLine());
			int r = Integer.parseInt(st.nextToken());
			int g = Integer.parseInt(st.nextToken());

			int MOD = (int)1e9 + 7;
			int H = getH (r , g);
			int dp [][] = new int[2][r + 1];

			dp[1][0] = 1;
			int parity = 0;
			for (int curH = 1 ; curH <= H ; ++ curH) {

				int neededBlocksSoFar = ((curH) * (curH + 1)) >> 1;

				dp[parity] = new int [r + 1];
				for (int red = Math.max(0 , Math.min(neededBlocksSoFar - g, curH)) ; red <= r ; ++ red) {

					if (red >= curH)
						dp[parity][red] = (dp[parity][red] + dp[parity ^ 1][red - curH ]);
					if (dp[parity][red] >= MOD) dp[parity][red] -= MOD;
					if (g >= neededBlocksSoFar - red)
						dp[parity][red] = (dp[parity][red] + dp[parity ^ 1][red]) % MOD;
					if (dp[parity][red] >= MOD) dp[parity][red] -= MOD;

				}
				parity ^= 1;
			}

			int cnt = 0 ;
			for (int i = 0 ; i <= r ; ++ i) {
				cnt = (cnt + dp[parity ^ 1][i]);
				if (cnt >= MOD) cnt -= MOD;
			}

			PrintWriter out = new PrintWriter(System.out);
			out.print((cnt % MOD)); out.flush(); out.close();
	}

}

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

public class Main {

	static long[][] dp;

	public static void main(String[] args) throws IOException{
        Scanner scan = new Scanner(System.in);
        int r = scan.nextInt();
        int g = scan.nextInt();
        long h = 1000000007;
        int size = r + g + 5;
        dp = new long[2][size];
        Arrays.fill(dp[0], 0);
        Arrays.fill(dp[1], 0);
        dp[0][0] = 1;
        dp[1][0] = 1;
        int max = 0;
        for(int i = 1; i < size; i++) {
        	int height = i * (i + 1) / 2;
        	if(height > r + g) break;
//        	while(true) {
//        		i++;
//        		height = (i * i + i) / 2;
//        		if(height > r +g) {
//        			i--;
//        			break;
//        		}
//        	}
        	int red = i & 1;
        	int green = 1 - red;
        	for(int j = 1; j <= height; j++) {
        		dp[red][j] = dp[green][j];
        		if(j >= i) {
        			dp[red][j] += dp[green][j-i];
        			dp[red][j] %= h;
        		}
        		else dp[red][j] %= h;
        	}
        	max = i;
        }
        long count = 0;
        long height = max * (max + 1) / 2;
        for(int i = 0; i <= r; i++){
        	if(height - i > g) continue;
        	int color = max & 1;
        	count += dp[color][i];
        	count %= h;
        }
		System.out.println(count);
	}
}

import java.util.Arrays;
import java.util.Scanner;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.InputStream;

/**
 * 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;
		Scanner in = new Scanner(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskD solver = new TaskD();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskD {
    private static int MOD = (int)1e9+7;

    public void solve(int testNumber, Scanner in, PrintWriter out) {
        int r = in.nextInt();
        int g = in.nextInt();

        int h = (int)((-1.0 + Math.sqrt(8.0*(r+g) + 1.0)) / 2.0);

        int dp[][] = new int[2][r+1];
        dp[0][r] = 1;

        for(int i = 1; i <= h; i++){
            int ii = i&1;
            Arrays.fill(dp[ii], 0);
            int til = Math.min(i * (i + 1) / 2, r);
            for(int j = r - til; j <= r; j++){
                if(j + i <= r) dp[ii][j] = (dp[ii][j] + dp[ii^1][j+i]) % MOD;
                int k = i*(i+1)/2 - (r-j);
                if(k <= g) dp[ii][j] = (dp[ii][j] + dp[ii^1][j]) % MOD;
            }
        }

        int ans = 0;
        for(int j = 0; j <= r; j++) ans = (ans + dp[h&1][j]) % MOD;

        out.println(ans);
    }
}

import java.util.Arrays;
import java.util.Scanner;

public class MainD {
	Scanner sc = new Scanner(System.in);
	final int MOD = 1000000007;

	void run() {
		int r = sc.nextInt();
		int g = sc.nextInt();
		int h = 0;
		while (h * (h + 1) / 2 <= r + g) h++;
		h--;

		int[] used = new int[h + 1];
		for (int i = 1; i <= h; i++) used[i] = used[i - 1] + h - i + 1;

		int[] pre = new int[r + 1];
		int[] next = new int[r + 1];
		pre[r] = 1;
		for (int i = 1; i <= h; i++) {
			for (int j = 0; j <= r; j++) {
				// i段目にrをh-i+1個使用するパターン
				if (j + h - i + 1 <= r && pre[j + h - i + 1] >= 1) {
					next[j] += pre[j + h - i + 1];
					next[j] %= MOD;
				}

				// i段目にgをh-i+1個使用するパターン
				int remGreen = r + g - j - used[i - 1];
				if (pre[j] >= 1 && remGreen >= h - i + 1) {
					next[j] += pre[j];
					next[j] %= MOD;
				}
			}
			for (int j = 0; j <= r; j++) {
				pre[j] = next[j];
				next[j] = 0;
			}
		}
		int ans = 0;
		for (int i = 0; i <= r; i++) {
			ans += pre[i];
			ans %= MOD;
		}
		System.out.println(ans);
	}

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

	void debug(Object... o) {
		System.out.println(Arrays.deepToString(o));
	}

	void debug2(int[][] array) {
		for (int i = 0; i < array.length; i++) {
			for (int j = 0; j < array[i].length; j++) {
				System.out.print(array[i][j]);
			}
			System.out.println();
		}
	}
}

import java.util.Scanner;

public class Main{

	static final int MOD = 1000000007;

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		while (in.hasNext()) {
			int r = in.nextInt(), g = in.nextInt();
			if (r > g) {
				r = r ^ g;
				g = r ^ g;
				r = r ^ g;
			}
			int h = 1, sum = r + g;
			while (sum >= 0)
				sum -= h++;
			h -= 2;
			sum = h * (h + 1) / 2;

			int dp[] = new int[r + 1];
			dp[0] = 1;
			for (int i = 1; i <= h; i++)
				for (int k = Math.min(r, i * (i + 1) / 2); k >= i; k--)
					dp[k] = (dp[k] + dp[k - i]) % MOD;
			int ans = 0;
			for (int i = Math.max(0, sum - g); i <= Math.min(sum, r); i++)
				ans = (ans + dp[i]) % MOD;
			System.out.println(ans);
		}
		in.close();
	}

}

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;
import java.util.Stack;
import java.util.StringTokenizer;

public class Main {
	static boolean can (int r , int g , int h) {
		while (h > 0 && (r > 0 || g > 0) && (r >= h || g >= h)) {
			if (r < g) {
				if (r >= h)
					r -= h;
				else g -= h;
			}

			else if (g >= h)
				g -= h;
			else r -= h;
			h -- ;
		}
		return h <= 0;
	}
	static int getH (int r , int g) {
		int lo = 0 ;
		int hi = (int)1e5;
		int max = 0;
		for(int i = 0 ; i < 20 ; ++i) {
			int mid = lo + ((hi - lo) >> 1);
			if (can(r , g , mid)) {
				max = Math.max(max, mid);
				lo = mid + 1;
			}
			else hi = mid - 1 ;
		}
		return max;
	}

	public static void main(String[] args) throws Exception {
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(bf.readLine());
			int r = Integer.parseInt(st.nextToken());
			int g = Integer.parseInt(st.nextToken());

			int MOD = (int)1e9 + 7;
			int H = getH (r , g);
			int dp [][] = new int[2][r + 1];

			dp[1][0] = 1;
			int parity = 0;
			for (int curH = 1 ; curH <= H ; ++ curH) {

				int neededBlocksSoFar = ((curH) * (curH + 1)) >> 1;

				dp[parity] = new int [r + 1];
				for (int red = Math.max(0 , Math.min(neededBlocksSoFar - g, curH)) ; red <= r ; ++ red) {

					if (red >= curH)
						dp[parity][red] = (dp[parity][red] + dp[parity ^ 1][red - curH ]);
					if (dp[parity][red] >= MOD) dp[parity][red] -= MOD;
					if (g >= neededBlocksSoFar - red)
						dp[parity][red] = (dp[parity][red] + dp[parity ^ 1][red]) % MOD;
					if (dp[parity][red] >= MOD) dp[parity][red] -= MOD;

				}
				parity ^= 1;
			}

			int cnt = 0 ;
			for (int i = 0 ; i <= r ; ++ i) {
				cnt = (cnt + dp[parity ^ 1][i]);
				if (cnt >= MOD) cnt -= MOD;
			}

			System.out.print((cnt % MOD));
	}

}

import java.util.*;

public class D {
	public static void main (String[] args) {
	    Scanner fs = new Scanner(System.in);

		//the time limit is way too strict for this problem
		//should be 3 sec if the intended solution complexity
		//is O(max * min(red, green))

		int red = fs.nextInt();
		int green = fs.nextInt();
		int max = bs(red, green);
//		while((max+1) * (max+2) / 2 <= red + green) max++;

		if(green < red) {
			int t = green;
			green = red;
			red = t;
		}

		int[] dp = new int[red+1];
		dp[0] = 1;
		long res = 0, mod = (int)1e9+7;
		for(int h = 1; h <= max; h++) {
			for(int r = Math.min(red, (h * (h+1))/2); r >= h; r--) {
				if(r-h < 0) break;
				dp[r] = (dp[r] + dp[r-h]);
				if(dp[r] >= mod) dp[r] -= mod;
			}
//			int index = h&1;
//			for(int r = 0; r <= red; r++) {
				//number of ways to build a tower with height h
				//and r red blocks.
//				dp[index][r] = 0;
//				int numGreens = h * (h+1) / 2 - r;
//				if(r - h >= 0) {
					//if I can at least build the bottom level
					//then the number of ways I can build a tower
					//with h-1 and r-h reds
//					dp[index][r] = (dp[index][r] + dp[index^1][r-h]);
//					if(dp[index][r] >= mod) dp[index][r] -= mod;
//				}
//
//				if(numGreens >= 0 && numGreens <= green) {
					//if the number of greens I need to complete this tower
					//is within the number of greens I have, then the number
					//of ways I can make a tower with r reds at level h
					//is just the number of ways I can make a tower with
					//r reds at level h-1 (since green is handling the rest)
//					dp[index][r] = (dp[index][r] + dp[index^1][r]);
//					if(dp[index][r] >= mod) dp[index][r] -= mod;
//				}
//			}
		}

		for(int i = 0; i <= red && i <= (max*max+max)/2; i++) {
			int take = (max*max+max)/2 - i;
			if(take <= green)
				res += dp[i];
		}
		res %= mod;
		System.out.println(res);
	}

	static int bs (int red, int green) {
		int res = 0;
		int lo = 1, hi = 895;
		for(int bs = 0; bs < 50 && lo <= hi; bs++) {
			int mid = (lo + hi) >> 1;
			int x = (mid+1)*(mid+2) / 2;
			if(x <= red+green) {
				res = Math.max(res, mid);
				lo = mid+1;
			}
			else {
				hi = mid-1;
			}
		}
		return ++res;
	}

}

/**
 * Created by Aminul on 12/19/2017.
 */

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

import static java.lang.Math.*;

public class CF478D_3 {
    static int R, G, dp[][], MAX_H, mod = (int)1e9+7;
    public static void main(String[] args) throws Exception {
        FastReader in = new FastReader(System.in);
        PrintWriter pw = new PrintWriter(System.out);

        R = in.nextInt(); G = in.nextInt();

        pw.println(solve());

        pw.close();
    }
    static int solve(){
        dp = new int[2][R+1];
        dp[0][0] = 1;
        int cur = 1, ways = 0;
        for(int i = 1; i < 900; i++){

            for(int j = 0; j <= R; j++){
                if(dp[cur ^ 1][j] == 0) continue;

                int h = i-1;
                int total = (h*(h+1))/2; // already total used balls
                h++; // current h
                int r = R - j; // remaining R
                int g = G - ( total - (R - r) ) ; // remaining G

                if(g >= h) dp[cur][j] += dp[cur ^ 1][j];
                if(dp[cur][j] > mod) dp[cur][j] -= mod;
                if(r >= h && j+h <= R){
                    dp[cur][j+h] +=  dp[cur ^ 1][j] ;
                    if(dp[cur][j+h] > mod) dp[cur][j+h] -= mod;
                }
            }

            int temp = 0;
            for(int j = 0; j <= R; j++){
                temp += dp[cur][j];
                if(temp > mod) temp -= mod;
                dp[cur^1][j] = 0;  // resetting for next iteration
            }
            if(temp > 0) ways = temp;

            cur ^= 1;

        }

        return ways;

    }

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

    static class FastReader {
        InputStream is;
        private byte[] inbuf = new byte[1024];
        private int lenbuf = 0, ptrbuf = 0;
        static final int ints[] = new int[128];

        public FastReader(InputStream is) {
            for (int i = '0'; i <= '9'; i++) ints[i] = i - '0';
            this.is = is;
        }

        public 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++];
        }

        public boolean isSpaceChar(int c) {
            return !(c >= 33 && c <= 126);
        }

        public int skip() {
            int b;
            while ((b = readByte()) != -1 && isSpaceChar(b)) ;
            return b;
        }

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

        public int nextInt() {
            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 << 3) + (num << 1) + ints[b];
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        public long nextLong() {
            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 << 3) + (num << 1) + ints[b];
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }
       /* public char nextChar() {
            return (char)skip();
        }*/

        public char[] next(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 buff[] = new char[1005];
        public char[] nextCharArray(){
            int b = skip(), p = 0;
            while(!(isSpaceChar(b))){
                buff[p++] = (char)b;
                b = readByte();
            }
            return Arrays.copyOf(buff, p);
        }*/
    }
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

public class C20141016RedGreen {
    public static void main(String args[]) throws IOException{
        PrintWriter out = new PrintWriter(System.out);
        out.println(f());
        out.close();
        System.exit(0);
    }
    public static int f() throws IOException{
        int BIG = 1000 * 1000 * 1000 + 7;
        BufferedReader f= new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(f.readLine());
        int r = Integer.parseInt(st.nextToken());
        int g = Integer.parseInt(st.nextToken());
        int h = 1;
        while (h * (h + 1) / 2 <= r + g)
            h ++;
        h --;
        int[] dp = new int[(h * (h + 1) / 2 + 1)];
        dp[0] = 1;
        for(int i = 1; i <= h; i++)
            for(int j = dp.length - 1; j >= i; j--)
                dp[j] = (dp[j - i] + dp[j]) % BIG;
        int sum = 0;
        for(int i = Math.max(dp.length - 1 - g, 0); i < Math.min(dp.length, r + 1); i++)
            sum = (sum + dp[i]) % BIG;
        return sum;
    }
}

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

public class D {

	static StringBuilder st = new StringBuilder();
	static final int MOD = (int)1e9 + 7 ;

	static int add(int x , int y)
	{
		int s = x + y ;
		if(s >= MOD)
			return s - MOD ;
		return s ;
	}

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

		int r = sc.nextInt() , g = sc.nextInt() , h = getLevels(r+g);

		int [][] dp = new int [2][g+1];

		Arrays.fill(dp[h & 1], 1);

		for(int level = h - 1 ; level >= 0 ; level --)
			for(int green = g , red =  r  + g - sum(level) - green ; green >= 0 ; green -- , red = r  + g - sum(level) - green)
			{
				int ans = 0 ;

				if(red - level - 1 >= 0)
					ans = add(ans , dp[(level & 1)^1][green]) ;

				if(green - level - 1 >= 0 )
					ans= add(ans, dp[(level & 1)^1][green - level - 1]);

				dp[level&1][green] = ans ;
			}

		out.println(dp[0][g]);

		out.flush();
		out.close();

	}
	static int getLevels(int total)
	{
		int start = 1 , end = 1000 , ans = 1;

		while(start <= end)
		{
			int n = (start + end) >> 1 ;

			if(sum(n) <= total)
			{
				ans = n ;
				start = n + 1 ;
			}
			else
				end = n - 1 ;
		}

		return ans ;

	}

	static int sum(int x)
	{
		return (x * (x + 1)) >> 1 ;
	}

	static class Scanner {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;

		Scanner() {
		}

		Scanner(String path) throws Exception {
			br = new BufferedReader(new FileReader(path));
		}

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

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

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

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

	static void shuffle(int[] a) {
		int n = a.length;
		for (int i = 0; i < n; i++) {
			int r = i + (int) (Math.random() * (n - i));
			int tmp = a[i];
			a[i] = a[r];
			a[r] = tmp;
		}
	}

	static void shuffle(char[] a) {
		int n = a.length;
		for (int i = 0; i < n; i++) {
			int r = i + (int) (Math.random() * (n - i));
			char tmp = a[i];
			a[i] = a[r];
			a[r] = tmp;
		}
	}

	static void shuffle(long[] a) {
		int n = a.length;
		for (int i = 0; i < n; i++) {
			int r = i + (int) (Math.random() * (n - i));
			long tmp = a[i];
			a[i] = a[r];
			a[r] = tmp;
		}
	}

	private static boolean oj = System.getProperty("ONLINE_JUDGE") != null;

	private static void tr(Object... o) {
		if (!oj)
			System.out.println(Arrays.deepToString(o));
	}

}

import java.util.*;
public class Test {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int r = in.nextInt();
        int g = in.nextInt();
        int h = 1;
        for ( ; h * (h + 1) / 2 <= r + g; ++h);
        h--;
        int[] dp = new int[r + 1];
        dp[0] = 1;
        int mod = 1000000007;
        long ret = 0;
        for (int i = 1; i <= h; ++i) {
            for (int j= r - i; j >= 0; --j) {
                dp[j + i] += dp[j];
                if (dp[j + i] >= mod) dp[j + i] -= mod;
            }
        }
        for (int j = 0; j <= r; ++j) {
            if (h * (h + 1) / 2 - j <= g) ret += dp[j];
        }
        System.out.println(ret % mod);
    }
}

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

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

	FastReader in = new FastReader();
	PrintWriter out = new PrintWriter(System.out);
	void run(){
		work();
		out.flush();
	}
	long mod=1000000007;
	long gcd(long a,long b) {
		return a==0?b:b>=a?gcd(b%a,a):gcd(b,a);
	}

	void work() {
		int n=in.nextInt(),m=in.nextInt();
		if(n>m) {
			int t=m;
			m=n;
			n=t;
		}
		int s=n+m;
		int k=(int)Math.sqrt(s*2);
		if(k*(k+1)>s*2) {
			k--;
		}
		s=(1+k)*k/2;
		long ret=0;
		k=Math.min(k, n);//最底层
		long[] dp=new long[n+1];
		dp[0]=1;
		for(int i=1;i<=k;i++) {
			for(int j=n;j>=i;j--) {
				dp[j]+=dp[j-i];
				dp[j]%=mod;
			}
		}
		for(int i=0;i<=n;i++) {
			if(s-i<=m) {
				ret+=dp[i];
				ret%=mod;
			}
		}
		out.println(ret);
	}
}

class FastReader
{
	BufferedReader br;
	StringTokenizer st;

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

	public String next()
	{
		while(st==null || !st.hasMoreElements())//回车，空行情况
		{
			try {
				st = new StringTokenizer(br.readLine());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return st.nextToken();
	}

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

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

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author aryssoncf
 */
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);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        final int MOD = MiscUtils.MOD7;

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            try {
                int R = in.readInt(), G = in.readInt();
                int nrow = 0;
                while ((nrow + 1) * (nrow + 2) <= 2 * (R + G)) {
                    nrow++;
                }
                int[][] dp = new int[2][R + 1];
                Arrays.fill(dp[(nrow + 1) & 1], 1);
                for (int row = nrow; row > 0; row--) {
                    int now = row & 1, pre = now ^ 1;
                    Arrays.fill(dp[now], 0);
                    for (int r = 0; r <= R; r++) {
                        int used = row * (row - 1) / 2, dr = R - r, dg = used - dr;
                        if (dg <= G) {
                            int g = G - dg;
                            if (row <= r) {
                                dp[now][r] += dp[pre][r - row];
                            }
                            if (row <= g) {
                                dp[now][r] += dp[pre][r];
                            }
                            dp[now][r] %= MOD;
                        }
                    }
                }
                int res = dp[1][R];
                out.printLine(res);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    static class MiscUtils {
        public static final int MOD7 = (int) (1e9 + 7);

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.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 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 {
            boolean isSpaceChar(int ch);

        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

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

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

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

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

    }
}

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

public class C {
	static int mod = (int)1e9+7;
	public static void main(String[] args) throws NumberFormatException, IOException {
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);
		int r = sc.nextInt(), g = sc.nextInt();
		int h = 1, sum = 1;
		while(sum <= r+g){
			sum += ++h;
		}
		int [][] dp = new int[2][r+1];
		Arrays.fill(dp[h%2], 1);
		int tot = h * (h-1) / 2;
		for (int i = h-1, cur = i%2; i > 0; --i, cur ^= 1) {
			tot -= i;
			for (int j = 0; j < dp[cur].length; ++j) {
				dp[cur][j] = 0;
				if(j - i >= 0)
					dp[cur][j] = dp[1^cur][j - i];
				//rem green blocks in level i
				int gg = g - (tot - (r-j));
				if(gg >= i)
					dp[cur][j] += dp[1^cur][j];
				if(dp[cur][j] >= mod)
					dp[cur][j] -= mod;
				}
		}
		out.println(dp[1][r]);
		out.close();
	}

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

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

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

		public int nextInt() throws NumberFormatException, IOException {
			return Integer.parseInt(next());
		}
	}

}

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

public class D478 {

    public static BufferedReader in;
    public static PrintWriter out;
    public static StringTokenizer tokenizer;

    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        in = new BufferedReader(new InputStreamReader(inputStream), 32768);
        out = new PrintWriter(outputStream);
        solve();
        out.close();
    }

    public static final int MOD = 1000000007;

    public static void solve() {
        int r = nextInt();
        int g = nextInt();
        int h = 1;
        while (h * (h + 1) / 2 <= (r + g)) {
            h++;
        }
        h--;
        int[] dp = new int[2 * 100000 + 100];
        dp[0] = 1;
        for (int j = 1; j <= h; j++) {
            for (int k = r; k >= 0; k--) {
                if (k >= j) {
                    dp[k] += dp[k - j];
                    dp[k] %= MOD;
                }
            }
        }
        long res = 0;
        long total = h * (h + 1) / 2;
        for (int i = 0; i <= r; i++) {
            if (g >= total - i) {
                res += dp[i];
                res %= MOD;
            }
        }
        boolean just;
        out.println(res);
    }

    public static String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(in.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

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

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

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

import java.util.Scanner;

public class D {
    public static final int MOD = 1000000007;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int r = sc.nextInt();
        int g = sc.nextInt();
        System.out.println(solve(r, g));
    }

    private static int solve(int r, int g) {
        if (r < g) {
            return solve(g, r);
        }
        int h = maxHeight(r + g);
        int[] a = new int[g + 1];
        a[0] = 1;
        for (int i = 1; i <= h; i++) {
            for (int j = g - i; j >= 0; j--) {
                a[i + j] = (a[i + j] + a[j]) % MOD;
            }
        }

        int res = 0;
        int blocks = h*(h+1)/2;
        for (int i = 0; i <= g; i++) {
            res = (res + (blocks - i <= r ? a[i] : 0)) % MOD;
        }
        return res;
    }

    private static int maxHeight(int blocks) {
        int c = blocks << 1;
        int d = (int)Math.sqrt(1 + 4 * c);
        int h = (d - 1) / 2;
        return h;
    }

}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class CR273_red_green_towers {

    private static final int M = 1000000007;

    public static void main(String... args) throws IOException {
        MyScanner sc = new MyScanner();

        int r = sc.nextInt();
        int g = sc.nextInt();

        long sum = 0L + r + g;

        int h = (int) Math.sqrt(sum * 2);
        if (1L * h * (h + 1) / 2 > sum) {
            h--;
        }

        if (r > g) {
            r = r ^ g;
            g = r ^ g;
            r = r ^ g;
        }

        int[] dp = new int[r + 2];

        dp[0] = 1;
        dp[1] = 1;

        for (int ch = 2; ch <= h; ch++) {
            int size = (int) (1L * ch * (ch + 1) / 2);
            for (int cr = Math.min(r, size); cr >= 0 ; cr--) {
                int cg = size - cr;
                int tmp = 0;
                if (cr >= ch) {
                    tmp = (tmp + dp[cr - ch]) % M;
                }
                if (cg >= ch) {
                    tmp = (tmp + dp[cr]) % M;
                }
                dp[cr] = tmp;
            }
        }

        int stackSize = (int) (1L * h * (h + 1) / 2);
        int left = (int) (sum - stackSize);
        long out = 0;
        for (int i = 0; i <= Math.min(left, r); i++) {
            out = (out + dp[r - i]) % M;
        }
        System.out.println(out);
    }

    static class MyScanner {

        BufferedReader br;
        StringTokenizer st;

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

        public String next() throws IOException {
            if (st == null || !st.hasMoreTokens()) {
                String line = br.readLine();
                while (line.isEmpty()) {
                    line = br.readLine();
                }
                st = new StringTokenizer(line);
            }
            return st.nextToken();
        }

        public int nextInt() throws IOException {
            String next = next();
            return Integer.parseInt(next);
        }

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

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.StringTokenizer;

/**
 * Created by yujiahao on 7/26/16.
 */
public class cf_273_d {
    private FastScanner in;
    private PrintWriter out;

    public void solve() throws IOException {
        int MOD = 1000000007;
        int r = in.nextInt();
        int g = in.nextInt();

        int h = 0;
        for(int i=0; i*(i+1)/2<=r+g; i++){
            h = i;
        }
        int[] dp = new int[g+1];
        dp[0] = 1;     //  dp[k]: 在 第 i 层之后还剩 K 个 g 的 情况总数

        for (int i=1; i<=h; i++){
            long sum = i*(i+1)/2;
            for (int j=g; j>=i; j--){
                if (sum-j<=r)   dp[j] = (dp[j]+dp[j-i])%MOD;
            }
        }
        long ans = 0;

        for (int i=0; i<=g; i++){
            if (h*(h+1)/2 - i<=r)   ans = (ans+dp[i])%MOD;
        }

        out.print(ans);
    }

    public void run() {
        try {
            in = new FastScanner();
            out = new PrintWriter(System.out);
            solve();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private class FastScanner {
        private BufferedReader br;
        private StringTokenizer st;

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

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

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

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

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

        public BigInteger nextBigInteger() { return new BigInteger(next());}

    }

    public static void main(String[] arg) {
        new cf_273_d().run();
    }
}

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

public class icpc
{
    public static final int M = (int)(1e9 + 7);
    public static void main(String[] args) throws IOException
    {
        Reader in = new Reader();
        //BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        int r = in.nextInt();
        int g = in.nextInt();
        int h = 0;
        for (int i=1;i<=1000;i++)
            if ((i * (i + 1)) / 2 > r + g)
            {
                h = i - 1;
                break;
            }

        long[] dp = new long[r + 1];
        dp[0] = 1;
        for (int i=1;i<=h;i++)
        {
            for (int j=r - i;j>=0;j--)
            {
                dp[j + i] += dp[j];
                dp[j + i] %= M;
            }
        }
        long ans = 0L;
        for (int i=0;i<=r;i++)
            if (h * (h + 1) / 2 - i <= g)
                ans += dp[i];
        System.out.println(ans % M);
    }
}
class DSU
{
    int[] parent;
    int[] size;
    //Pass number of total nodes as parameter to the constructor
    DSU(int n)
    {
        this.parent = new int[n];
        this.size = new int[n];
        Arrays.fill(parent, -1);
    }

    public void makeSet(int v)
    {
        parent[v] = v;
        size[v] = 1;
    }

    public int findSet(int v)
    {
        if (v == parent[v]) return v;
        return parent[v] = findSet(parent[v]);
    }

    public void unionSets(int a, int b)
    {
        a = findSet(a);
        b = findSet(b);
        if (a != b)
        {
            if (size[a] < size[b])
            {
                int temp = a;
                a = b;
                b = temp;
            }
            parent[b] = a;
            size[a] += size[b];
        }
    }
}
class FastFourierTransform
{
    private void fft(double[] a, double[] b, boolean invert)
    {
        int count = a.length;
        for (int i = 1, j = 0; i < count; i++)
        {
            int bit = count >> 1;
            for (; j >= bit; bit >>= 1)
                j -= bit;
            j += bit;
            if (i < j)
            {
                double temp = a[i];
                a[i] = a[j];
                a[j] = temp;
                temp = b[i];
                b[i] = b[j];
                b[j] = temp;
            }
        }
        for (int len = 2; len <= count; len <<= 1)
        {
            int halfLen = len >> 1;
            double angle = 2 * Math.PI / len;
            if (invert)
                angle = -angle;
            double wLenA = Math.cos(angle);
            double wLenB = Math.sin(angle);
            for (int i = 0; i < count; i += len)
            {
                double wA = 1;
                double wB = 0;
                for (int j = 0; j < halfLen; j++)
                {
                    double uA = a[i + j];
                    double uB = b[i + j];
                    double vA = a[i + j + halfLen] * wA - b[i + j + halfLen] * wB;
                    double vB = a[i + j + halfLen] * wB + b[i + j + halfLen] * wA;
                    a[i + j] = uA + vA;
                    b[i + j] = uB + vB;
                    a[i + j + halfLen] = uA - vA;
                    b[i + j + halfLen] = uB - vB;
                    double nextWA = wA * wLenA - wB * wLenB;
                    wB = wA * wLenB + wB * wLenA;
                    wA = nextWA;
                }
            }
        }
        if (invert)
        {
            for (int i = 0; i < count; i++)
            {
                a[i] /= count;
                b[i] /= count;
            }
        }
    }

    public long[] multiply(long[] a, long[] b)
    {
        int resultSize = Integer.highestOneBit(Math.max(a.length, b.length) - 1) << 2;
        resultSize = Math.max(resultSize, 1);
        double[] aReal = new double[resultSize];
        double[] aImaginary = new double[resultSize];
        double[] bReal = new double[resultSize];
        double[] bImaginary = new double[resultSize];
        for (int i = 0; i < a.length; i++)
            aReal[i] = a[i];
        for (int i = 0; i < b.length; i++)
            bReal[i] = b[i];
        fft(aReal, aImaginary, false);
        fft(bReal, bImaginary, false);
        for (int i = 0; i < resultSize; i++)
        {
            double real = aReal[i] * bReal[i] - aImaginary[i] * bImaginary[i];
            aImaginary[i] = aImaginary[i] * bReal[i] + bImaginary[i] * aReal[i];
            aReal[i] = real;
        }
        fft(aReal, aImaginary, true);
        long[] result = new long[resultSize];
        for (int i = 0; i < resultSize; i++)
            result[i] = Math.round(aReal[i]);
        return result;
    }
}
class NumberTheory
{
    public boolean isPrime(long n)
    {
        if(n < 2)
            return false;
        for(long x = 2;x * x <= n;x++)
        {
            if(n % x == 0)
                return false;
        }
        return true;
    }
    public ArrayList<Long> primeFactorisation(long n)
    {
        ArrayList<Long> f = new ArrayList<>();
        for(long x=2;x * x <= n;x++)
        {
            while(n % x == 0)
            {
                f.add(x);
                n /= x;
            }
        }
        if(n > 1)
            f.add(n);
        return f;
    }
    public int[] sieveOfEratosthenes(int n)
    {
        //Returns an array with the smallest prime factor for each number and primes marked as 0
        int[] sieve = new int[n + 1];
        for(int x=2;x * x <= n;x++)
        {
            if(sieve[x] != 0)
                continue;
            for(int u=x*x;u<=n;u+=x)
            {
                if(sieve[u] == 0)
                {
                    sieve[u] = x;
                }
            }
        }
        return sieve;
    }
    public long gcd(long a, long b)
    {
        if(b == 0)
            return a;
        return gcd(b, a % b);
    }
    public long phi(long n)
    {
        double result = n;

        for(long p=2;p*p<=n;p++)
        {
            if(n % p == 0)
            {
                while (n % p == 0)
                    n /= p;
                result *= (1.0 - (1.0 / (double)p));
            }
        }
        if(n > 1)
            result *= (1.0 - (1.0 / (double)n));
        return (long)result;
    }
    public Name extendedEuclid(long a, long b)
    {
        if(b == 0)
            return new Name(a, 1, 0);
        Name n1 = extendedEuclid(b, a % b);
        Name n2 = new Name(n1.d, n1.y, n1.x - (long)Math.floor((double)a / b) * n1.y);
        return n2;
    }
    public long modularExponentiation(long a, long b, long n)
    {
        long d = 1L;
        String bString = Long.toBinaryString(b);
        for(int i=0;i<bString.length();i++)
        {
            d = (d * d) % n;
            if(bString.charAt(i) == '1')
                d = (d * a) % n;
        }
        return d;
    }
}
class Name
{
    long d;
    long x;
    long y;

    public Name(long d, long x, long y)
    {
        this.d = d;
        this.x = x;
        this.y = y;
    }
}
class SuffixArray
{
    int ALPHABET_SZ = 256, N;
    int[] T, lcp, sa, sa2, rank, tmp, c;

    public SuffixArray(String str)
    {
        this(toIntArray(str));
    }

    private static int[] toIntArray(String s)
    {
        int[] text = new int[s.length()];
        for (int i = 0; i < s.length(); i++) text[i] = s.charAt(i);
        return text;
    }

    public SuffixArray(int[] text)
    {
        T = text;
        N = text.length;
        sa = new int[N];
        sa2 = new int[N];
        rank = new int[N];
        c = new int[Math.max(ALPHABET_SZ, N)];
        construct();
        kasai();
    }

    private void construct()
    {
        int i, p, r;
        for (i = 0; i < N; ++i) c[rank[i] = T[i]]++;
        for (i = 1; i < ALPHABET_SZ; ++i) c[i] += c[i - 1];
        for (i = N - 1; i >= 0; --i) sa[--c[T[i]]] = i;
        for (p = 1; p < N; p <<= 1)
        {
            for (r = 0, i = N - p; i < N; ++i) sa2[r++] = i;
            for (i = 0; i < N; ++i) if (sa[i] >= p) sa2[r++] = sa[i] - p;
            Arrays.fill(c, 0, ALPHABET_SZ, 0);
            for (i = 0; i < N; ++i) c[rank[i]]++;
            for (i = 1; i < ALPHABET_SZ; ++i) c[i] += c[i - 1];
            for (i = N - 1; i >= 0; --i) sa[--c[rank[sa2[i]]]] = sa2[i];
            for (sa2[sa[0]] = r = 0, i = 1; i < N; ++i)
            {
                if (!(rank[sa[i - 1]] == rank[sa[i]]
                        && sa[i - 1] + p < N
                        && sa[i] + p < N
                        && rank[sa[i - 1] + p] == rank[sa[i] + p])) r++;
                sa2[sa[i]] = r;
            }
            tmp = rank;
            rank = sa2;
            sa2 = tmp;
            if (r == N - 1) break;
            ALPHABET_SZ = r + 1;
        }
    }

    private void kasai()
    {
        lcp = new int[N];
        int[] inv = new int[N];
        for (int i = 0; i < N; i++) inv[sa[i]] = i;
        for (int i = 0, len = 0; i < N; i++)
        {
            if (inv[i] > 0)
            {
                int k = sa[inv[i] - 1];
                while ((i + len < N) && (k + len < N) && T[i + len] == T[k + len]) len++;
                lcp[inv[i] - 1] = len;
                if (len > 0) len--;
            }
        }
    }
}
class ZAlgorithm
{
    public int[] calculateZ(char input[])
    {
        int Z[] = new int[input.length];
        int left = 0;
        int right = 0;
        for(int k = 1; k < input.length; k++) {
            if(k > right) {
                left = right = k;
                while(right < input.length && input[right] == input[right - left]) {
                    right++;
                }
                Z[k] = right - left;
                right--;
            } else {
                //we are operating inside box
                int k1 = k - left;
                //if value does not stretches till right bound then just copy it.
                if(Z[k1] < right - k + 1) {
                    Z[k] = Z[k1];
                } else { //otherwise try to see if there are more matches.
                    left = k;
                    while(right < input.length && input[right] == input[right - left]) {
                        right++;
                    }
                    Z[k] = right - left;
                    right--;
                }
            }
        }
        return Z;
    }
    public ArrayList<Integer> matchPattern(char text[], char pattern[])
    {
        char newString[] = new char[text.length + pattern.length + 1];
        int i = 0;
        for(char ch : pattern) {
            newString[i] = ch;
            i++;
        }
        newString[i] = '$';
        i++;
        for(char ch : text) {
            newString[i] = ch;
            i++;
        }
        ArrayList<Integer> result = new ArrayList<>();
        int Z[] = calculateZ(newString);

        for(i = 0; i < Z.length ; i++) {
            if(Z[i] == pattern.length) {
                result.add(i - pattern.length - 1);
            }
        }
        return result;
    }
}
class KMPAlgorithm
{
    public int[] computeTemporalArray(char[] pattern)
    {
        int[] lps = new int[pattern.length];

        int index = 0;
        for(int i=1;i<pattern.length;)
        {
            if(pattern[i] == pattern[index])
            {
                lps[i] = index + 1;
                index++;
                i++;
            }
            else
            {
                if(index != 0)
                {
                    index = lps[index - 1];
                }
                else
                {
                    lps[i] = 0;
                    i++;
                }
            }
        }
        return lps;
    }

    public ArrayList<Integer> KMPMatcher(char[] text, char[] pattern)
    {
        int[] lps = computeTemporalArray(pattern);

        int j = 0;
        int i = 0;
        int n = text.length;
        int m = pattern.length;
        ArrayList<Integer> indices = new ArrayList<>();
        while(i < n)
        {
            if(pattern[j] == text[i])
            {
                i++;
                j++;
            }
            if(j == m)
            {
                indices.add(i - j);
                j = lps[j - 1];
            }
            else if(i < n && pattern[j] != text[i])
            {
                if(j != 0)
                    j = lps[j - 1];
                else
                    i = i + 1;
            }
        }
        return indices;
    }
}
class Hashing
{
    public long[] computePowers(long p, int n, long m)
    {
        long[] powers = new long[n];
        powers[0] = 1;
        for(int i=1;i<n;i++)
        {
            powers[i] = (powers[i - 1] * p) % m;
        }
        return powers;
    }
    public long computeHash(String s)
    {
        long p = 31;
        long m = 1_000_000_009;
        long hashValue = 0L;
        long[] powers = computePowers(p, s.length(), m);
        for(int i=0;i<s.length();i++)
        {
            char ch = s.charAt(i);
            hashValue = (hashValue + (ch - 'a' + 1) * powers[i]) % m;
        }
        return hashValue;
    }
}
class BasicFunctions
{
    public int maxOfIntArray(int[] A)
    {
        int max = Integer.MIN_VALUE;
        for (int i=0;i<A.length;i++)    max = Math.max(max, A[i]);
        return max;
    }
    public long maxOfLongArray(long[] A)
    {
        long max = Long.MIN_VALUE;
        for (int i=0;i<A.length;i++)    max = Math.max(max, A[i]);
        return max;
    }
    public int minOfIntArray(int[] A)
    {
        int min = Integer.MAX_VALUE;
        for (int i=0;i<A.length;i++)    min = Math.min(min, A[i]);
        return min;
    }
    public long minOfLongArray(long[] A)
    {
        long min = Long.MAX_VALUE;
        for (int i=0;i<A.length;i++)    min = Math.min(min, A[i]);
        return min;
    }

}
class MergeSortInt
{
    // Merges two subarrays of arr[].
    // First subarray is arr[l..m]
    // Second subarray is arr[m+1..r]
    void merge(int arr[], int l, int m, int r) {
        // Find sizes of two subarrays to be merged
        int n1 = m - l + 1;
        int n2 = r - m;

        /* Create temp arrays */
        int L[] = new int[n1];
        int R[] = new int[n2];

        /*Copy data to temp arrays*/
        for (int i = 0; i < n1; ++i)
            L[i] = arr[l + i];
        for (int j = 0; j < n2; ++j)
            R[j] = arr[m + 1 + j];

        /* Merge the temp arrays */

        // Initial indexes of first and second subarrays
        int i = 0, j = 0;

        // Initial index of merged subarry array
        int k = l;
        while (i < n1 && j < n2) {
            if (L[i] <= R[j]) {
                arr[k] = L[i];
                i++;
            } else {
                arr[k] = R[j];
                j++;
            }
            k++;
        }

        /* Copy remaining elements of L[] if any */
        while (i < n1) {
            arr[k] = L[i];
            i++;
            k++;
        }

        /* Copy remaining elements of R[] if any */
        while (j < n2) {
            arr[k] = R[j];
            j++;
            k++;
        }
    }

    // Main function that sorts arr[l..r] using
    // merge()
    void sort(int arr[], int l, int r) {
        if (l < r) {
            // Find the middle point
            int m = (l + r) / 2;

            // Sort first and second halves
            sort(arr, l, m);
            sort(arr, m + 1, r);

            // Merge the sorted halves
            merge(arr, l, m, r);
        }
    }

}
class MergeSortLong
{
    // Merges two subarrays of arr[].
    // First subarray is arr[l..m]
    // Second subarray is arr[m+1..r]
    void merge(long arr[], int l, int m, int r) {
        // Find sizes of two subarrays to be merged
        int n1 = m - l + 1;
        int n2 = r - m;

        /* Create temp arrays */
        long L[] = new long[n1];
        long R[] = new long[n2];

        /*Copy data to temp arrays*/
        for (int i = 0; i < n1; ++i)
            L[i] = arr[l + i];
        for (int j = 0; j < n2; ++j)
            R[j] = arr[m + 1 + j];

        /* Merge the temp arrays */

        // Initial indexes of first and second subarrays
        int i = 0, j = 0;

        // Initial index of merged subarry array
        int k = l;
        while (i < n1 && j < n2) {
            if (L[i] <= R[j]) {
                arr[k] = L[i];
                i++;
            } else {
                arr[k] = R[j];
                j++;
            }
            k++;
        }

        /* Copy remaining elements of L[] if any */
        while (i < n1) {
            arr[k] = L[i];
            i++;
            k++;
        }

        /* Copy remaining elements of R[] if any */
        while (j < n2) {
            arr[k] = R[j];
            j++;
            k++;
        }
    }

    // Main function that sorts arr[l..r] using
    // merge()
    void sort(long arr[], int l, int r) {
        if (l < r) {
            // Find the middle point
            int m = (l + r) / 2;

            // Sort first and second halves
            sort(arr, l, m);
            sort(arr, m + 1, r);

            // Merge the sorted halves
            merge(arr, l, m, r);
        }
    }
}
class Node
{

    int x;
    int y;

    public Node(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(Object ob)
    {
        if(ob == null)
            return false;
        if(!(ob instanceof Node))
            return false;
        if(ob == this)
            return true;
        Node obj = (Node)ob;
        if(this.x == obj.x && this.y == obj.y)
            return true;
        return false;
    }

    @Override
    public int hashCode()
    {
        return (int)this.x;
    }
}
class Reader
{
    final private int BUFFER_SIZE = 1 << 16;
    private DataInputStream din;
    private byte[] buffer;
    private int bufferPointer, bytesRead;

    public Reader()
    {
        din = new DataInputStream(System.in);
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public Reader(String file_name) throws IOException
    {
        din = new DataInputStream(new FileInputStream(file_name));
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public String readLine() throws IOException
    {
        byte[] buf = new byte[64]; // line length
        int cnt = 0, c;
        while ((c = read()) != -1)
        {
            if (c == '\n')
                break;
            buf[cnt++] = (byte) c;
        }
        return new String(buf, 0, cnt);
    }

    public int nextInt() throws IOException
    {
        int ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do
        {
            ret = ret * 10 + c - '0';
        }  while ((c = read()) >= '0' && c <= '9');

        if (neg)
            return -ret;
        return ret;
    }

    public long nextLong() throws IOException
    {
        long ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');
        if (neg)
            return -ret;
        return ret;
    }

    public double nextDouble() throws IOException
    {
        double ret = 0, div = 1;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();

        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');

        if (c == '.')
        {
            while ((c = read()) >= '0' && c <= '9')
            {
                ret += (c - '0') / (div *= 10);
            }
        }

        if (neg)
            return -ret;
        return ret;
    }

    private void fillBuffer() throws IOException
    {
        bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
        if (bytesRead == -1)
            buffer[0] = -1;
    }

    private byte read() throws IOException
    {
        if (bufferPointer == bytesRead)
            fillBuffer();
        return buffer[bufferPointer++];
    }

    public void close() throws IOException
    {
        if (din == null)
            return;
        din.close();
    }
}
class SegmentTree
{
    public int nextPowerOfTwo(int num)
    {
        if(num == 0)
            return 1;
        if(num > 0 && (num & (num - 1)) == 0)
            return num;
        while((num &(num - 1)) > 0)
        {
            num = num & (num - 1);
        }
        return num << 1;
    }
    public int[] createSegmentTree(int[] input)
    {
        int np2 = nextPowerOfTwo(input.length);
        int[] segmentTree = new int[np2 * 2 - 1];

        for(int i=0;i<segmentTree.length;i++)
            segmentTree[i] = Integer.MIN_VALUE;

        constructSegmentTree(segmentTree,input,0,input.length-1,0);
        return segmentTree;

    }
    private void constructSegmentTree(int[] segmentTree,int[] input,int low,int high,int pos)
    {
        if(low == high)
        {
            segmentTree[pos] = input[low];
            return;
        }
        int mid = (low + high)/ 2;
        constructSegmentTree(segmentTree,input,low,mid,2*pos + 1);
        constructSegmentTree(segmentTree,input,mid+1,high,2*pos + 2);
        segmentTree[pos] = Math.max(segmentTree[2*pos + 1],segmentTree[2*pos + 2]);
    }
    public int rangeMinimumQuery(int []segmentTree,int qlow,int qhigh,int len)
    {
        return rangeMinimumQuery(segmentTree,0,len-1,qlow,qhigh,0);
    }
    private int rangeMinimumQuery(int segmentTree[],int low,int high,int qlow,int qhigh,int pos)
    {
        if(qlow <= low && qhigh >= high){
            return segmentTree[pos];
        }
        if(qlow > high || qhigh < low){
            return Integer.MIN_VALUE;
        }
        int mid = (low+high)/2;
        return Math.max(rangeMinimumQuery(segmentTree, low, mid, qlow, qhigh, 2 * pos + 1),
                rangeMinimumQuery(segmentTree, mid + 1, high, qlow, qhigh, 2 * pos + 2));
    }
}
class Trie
{

    private class TrieNode
    {
        Map<Character, TrieNode> children;
        boolean endOfWord;
        public TrieNode()
        {
            children = new HashMap<>();
            endOfWord = false;
        }
    }

    private final TrieNode root;
    public Trie()
    {
        root = new TrieNode();
    }

    public void insert(String word)
    {
        TrieNode current = root;
        for (int i = 0; i < word.length(); i++)
        {
            char ch = word.charAt(i);
            TrieNode node = current.children.get(ch);
            if (node == null)
            {
                node = new TrieNode();
                current.children.put(ch, node);
            }
            current = node;
        }
        current.endOfWord = true;
    }

    public boolean search(String word)
    {
        TrieNode current = root;
        for (int i = 0; i < word.length(); i++)
        {
            char ch = word.charAt(i);
            TrieNode node = current.children.get(ch);
            if (node == null)
            {
                return false;
            }
            current = node;
        }
        return current.endOfWord;
    }

    public void delete(String word)
    {
        delete(root, word, 0);
    }

    private boolean delete(TrieNode current, String word, int index)
    {
        if (index == word.length())
        {
            if (!current.endOfWord)
            {
                return false;
            }
            current.endOfWord = false;
            return current.children.size() == 0;
        }
        char ch = word.charAt(index);
        TrieNode node = current.children.get(ch);
        if (node == null)
        {
            return false;
        }
        boolean shouldDeleteCurrentNode = delete(node, word, index + 1);

        if (shouldDeleteCurrentNode)
        {
            current.children.remove(ch);
            return current.children.size() == 0;
        }
        return false;
    }
}
class SegmentTreeLazy
{
    public int nextPowerOfTwo(int num)
    {
        if(num == 0)
            return 1;
        if(num > 0 && (num & (num - 1)) == 0)
            return num;
        while((num &(num - 1)) > 0)
        {
            num = num & (num - 1);
        }
        return num << 1;
    }

    public int[] createSegmentTree(int input[])
    {
        int nextPowOfTwo = nextPowerOfTwo(input.length);
        int segmentTree[] = new int[nextPowOfTwo*2 -1];

        for(int i=0; i < segmentTree.length; i++){
            segmentTree[i] = Integer.MAX_VALUE;
        }
        constructMinSegmentTree(segmentTree, input, 0, input.length - 1, 0);
        return segmentTree;
    }

    private void constructMinSegmentTree(int segmentTree[], int input[], int low, int high,int pos)
    {
        if(low == high)
        {
            segmentTree[pos] = input[low];
            return;
        }
        int mid = (low + high)/2;
        constructMinSegmentTree(segmentTree, input, low, mid, 2 * pos + 1);
        constructMinSegmentTree(segmentTree, input, mid + 1, high, 2 * pos + 2);
        segmentTree[pos] = Math.min(segmentTree[2*pos+1], segmentTree[2*pos+2]);
    }

    public void updateSegmentTreeRangeLazy(int input[], int segmentTree[], int lazy[], int startRange, int endRange, int delta)
    {
        updateSegmentTreeRangeLazy(segmentTree, lazy, startRange, endRange, delta, 0, input.length - 1, 0);
    }

    private void updateSegmentTreeRangeLazy(int segmentTree[], int lazy[], int startRange, int endRange, int delta, int low, int high, int pos)
    {
        if(low > high)
        {
            return;
        }
        if (lazy[pos] != 0)
        {
            segmentTree[pos] += lazy[pos];
            if (low != high)
            {
                lazy[2 * pos + 1] += lazy[pos];
                lazy[2 * pos + 2] += lazy[pos];
            }
            lazy[pos] = 0;
        }

        if(startRange > high || endRange < low)
        {
            return;
        }

        if(startRange <= low && endRange >= high)
        {
            segmentTree[pos] += delta;
            if(low != high) {
                lazy[2*pos + 1] += delta;
                lazy[2*pos + 2] += delta;
            }
            lazy[pos] = 0;
        }

        int mid = (low + high)/2;
        updateSegmentTreeRangeLazy(segmentTree, lazy, startRange, endRange, delta, low, mid, 2*pos+1);
        updateSegmentTreeRangeLazy(segmentTree, lazy, startRange, endRange, delta, mid+1, high, 2*pos+2);
        segmentTree[pos] = Math.min(segmentTree[2*pos + 1], segmentTree[2*pos + 2]);
    }

    public int rangeMinimumQueryLazy(int segmentTree[], int lazy[], int qlow, int qhigh, int len)
    {
        return rangeMinimumQueryLazy(segmentTree, lazy, qlow, qhigh, 0, len - 1, 0);
    }

    private int rangeMinimumQueryLazy(int segmentTree[], int lazy[], int qlow, int qhigh, int low, int high, int pos)
    {
        if(low > high)
        {
            return Integer.MAX_VALUE;
        }
        if (lazy[pos] != 0)
        {
            segmentTree[pos] += lazy[pos];
            if (low != high)
            {
                lazy[2 * pos + 1] += lazy[pos];
                lazy[2 * pos + 2] += lazy[pos];
            }
            lazy[pos] = 0;
        }

        if(qlow > high || qhigh < low)
        {
            return Integer.MAX_VALUE;
        }

        if(qlow <= low && qhigh >= high)
        {
            return segmentTree[pos];
        }

        int mid = (low+high)/2;
        return Math.min(rangeMinimumQueryLazy(segmentTree, lazy, qlow, qhigh, low, mid, 2 * pos + 1), rangeMinimumQueryLazy(segmentTree, lazy,  qlow, qhigh, mid + 1, high, 2 * pos + 2));
    }
}
class BIT
{
    int size;
    int[] table;
    public BIT(int size)
    {
        table = new int[size];
        this.size = size;
    }

    void update(int i, long delta)
    {
        while (i < size)
        {
            table[i] += delta;
            i += Integer.lowestOneBit(i);
        }
    }

    int sum(int i)
    {
        int sum = 0;
        while (i > 0)
        {
            sum += table[i];
            i -= Integer.lowestOneBit(i);
        }
        return sum;
    }
}

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;
import java.util.Stack;
import java.util.StringTokenizer;

public class Main {
	static boolean can (int r , int g , int h) {
		while (h > 0 && (r > 0 || g > 0) && (r >= h || g >= h)) {
			if (r < g) {
				if (r >= h)
					r -= h;
				else g -= h;
			}

			else if (g >= h)
				g -= h;
			else r -= h;
			h -- ;
		}
		return h <= 0;
	}
	static int getH (int r , int g) {
		int lo = 0 ;
		int hi = (int)1e5;
		int max = 0;
		for(int i = 0 ; i < 20 ; ++i) {
			int mid = lo + ((hi - lo) >> 1);
			if (can(r , g , mid)) {
				max = Math.max(max, mid);
				lo = mid + 1;
			}
			else hi = mid - 1 ;
		}
		return max;
	}

	public static void main(String[] args) throws Exception {
		Scanner sc = new Scanner(System.in);
		int r = sc.nextInt();
		int g = sc.nextInt();
			int MOD = (int)1e9 + 7;
			int H = getH (r , g);
			int dp [][] = new int[2][r + 1];

			dp[1][0] = 1;
			int parity = 0;
			for (int curH = 1 ; curH <= H ; ++ curH) {

				int neededBlocksSoFar = ((curH) * (curH + 1)) >> 1;

				dp[parity] = new int [r + 1];
				for (int red = Math.max(0 , Math.min(neededBlocksSoFar - g, curH)) ; red <= r ; ++ red) {

					if (red >= curH)
						dp[parity][red] = (dp[parity][red] + dp[parity ^ 1][red - curH ]);
					if (dp[parity][red] >= MOD) dp[parity][red] -= MOD;
					if (g >= neededBlocksSoFar - red)
						dp[parity][red] = (dp[parity][red] + dp[parity ^ 1][red]) % MOD;
					if (dp[parity][red] >= MOD) dp[parity][red] -= MOD;

				}
				parity ^= 1;
			}

			int cnt = 0 ;
			for (int i = 0 ; i <= r ; ++ i) {
				cnt = (cnt + dp[parity ^ 1][i]);
				if (cnt >= MOD) cnt -= MOD;
			}

			PrintWriter out = new PrintWriter(System.out);
			System.out.print((cnt % MOD)); out.flush(); out.close();
	}

}

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

public class Main{
    final boolean isFileIO = false;
    BufferedReader in;
    PrintWriter out;
    StringTokenizer st = new StringTokenizer("");
    String delim = " ";

    public static void main(String[] args) throws IOException {
        Main m = new Main();
        m.initIO();
        m.solve();
        m.in.close();
        m.out.close();
    }

    public void initIO() throws IOException {
        if(!isFileIO) {
            in = new BufferedReader(new InputStreamReader(System.in));
            out = new PrintWriter(System.out);
        } else {
            in = new BufferedReader(new FileReader("input.txt"));
            out = new PrintWriter("output.txt");
        }
    }

    String nextToken() throws IOException {
        if(!st.hasMoreTokens()) {
            st = new StringTokenizer(in.readLine());
        }
        return st.nextToken(delim);
    }

    String readLine() throws IOException {
        return in.readLine();
    }

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

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

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

    int r, g;
    public void solve() throws IOException {
        r = nextInt(); g = nextInt();
        int left = 1;
        boolean[] cur = new boolean[r + 1];
        int right = (int)Math.sqrt((2 * (r + g))) + 1;

        int h = 1;
        cur[0] = true;
        for(int i = 1; i <= right; i++) {
            boolean can = false;
            for(int j = r; j >= i; j--) {
                cur[j] = cur[j - i];
            }
            int all = (i * (i + 1)) / 2;
            for(int j = 0; j <= r; j++) {
                if(all - j <= g && cur[j]) {
                    can = true;
                }
            }
            if(can) {
                h = i;
            } else {
                break;
            }
        }
        left = h;
        int all = (left * (left + 1)) / 2;
        int[] dp = new int[r + 1];
        dp[0] = 1;
        int mod = 1_000_000_007;
        for(int i = 1; i <= left; i++) {
            for(int j = r; j >= i; j--) {
                dp[j] = (dp[j] + dp[j - i]) % mod;
            }
        }
        int ans = 0;
        for(int i = 0; i <= r; i++) {
            if(all - i <= g) {
                ans = (ans + dp[i]) % mod;
            }
        }
        out.println(ans);
    }

}

class Utils {

    public static long binpow(long a, long exp, long mod) {
        if(exp == 0) {
            return 1;
        }
        if(exp % 2 == 0) {
            long temp = binpow(a, exp / 2, mod);
            return (temp * temp) % mod;
        } else {
            return (binpow(a, exp - 1, mod) * a) % mod;
        }
    }

    public static long inv(long a, long mod) {
        return binpow(a, mod - 2, mod);
    }

    public static long addmod(long a, long b, long mod) {
        return (a + b + 2 * mod) % mod;
    }
}

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

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

	FastReader in = new FastReader();
	PrintWriter out = new PrintWriter(System.out);
	void run(){
		work();
		out.flush();
	}
	long mod=1000000007;
	long gcd(long a,long b) {
		return a==0?b:b>=a?gcd(b%a,a):gcd(b,a);
	}

	void work() {
		int n=in.nextInt(),m=in.nextInt();
		if(n>m) {
			int t=m;
			m=n;
			n=t;
		}
		int s=n+m;
		int k=(int)Math.sqrt(s*2);
		if(k*(k+1)>s*2) {
			k--;
		}
		s=(1+k)*k/2;
		long ret=0;
		k=Math.min(k, n);//最底层
		long[] dp=new long[n+1];
		dp[0]=1;
		for(int i=1;i<=k;i++) {
			for(int j=Math.min((1+k)*k/2, n);j>=i;j--) {
				dp[j]+=dp[j-i];
				dp[j]%=mod;
			}
		}
		for(int i=0;i<=n;i++) {
			if(s-i<=m) {
				ret+=dp[i];
				ret%=mod;
			}
		}
		out.println(ret);
	}
}

class FastReader
{
	BufferedReader br;
	StringTokenizer st;

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

	public String next()
	{
		while(st==null || !st.hasMoreElements())//回车，空行情况
		{
			try {
				st = new StringTokenizer(br.readLine());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return st.nextToken();
	}

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

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

// Codeforces Round #273 (Div.2) D. Red-Green Towers (478/D)

import java.util.Scanner;

public class RedGreenTowers {

	private static final int MOD = 1000000007;

	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);

		int R = scan.nextInt();
		int G = scan.nextInt();

		int[][] dp = new int[2][R + 1];
		int curr = 0;
		int res = 0;
		dp[1][0] = 1;
		for (int h = 1, sum = 1; sum <= R + G; sum += ++h) {
			int prev = 1 - curr;
			res = 0;
			for (int r = Math.max(0, sum - G); r <= R; ++r) {
				dp[curr][r] = dp[prev][r];
				if (r - h >= 0) {
					dp[curr][r] = (dp[curr][r] + dp[prev][r - h]) % MOD;
				}
				res = (res + dp[curr][r]) % MOD;
			}
			curr = prev;
		}
		System.out.println(res);
	}
}

import java.io.BufferedReader;
// import java.io.FileInputStream;
// import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.TreeSet;

import static java.lang.Math.abs;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.Math.round;
import static java.util.Arrays.copyOf;
import static java.util.Arrays.fill;
import static java.util.Arrays.sort;
import static java.util.Collections.reverseOrder;
import static java.util.Collections.sort;
import static java.util.Comparator.comparing;

public class Main {
    FastScanner in;
    PrintWriter out;

    private void solve() throws IOException {
        long mod = (long) 1e9 + 7;
        int green = in.nextInt(), red = in.nextInt(), height = 0;
        for (int sum = 0; sum <= red + green; sum += ++height) ;
        height--;

        long[] cnt = new long[green + 1];
        cnt[0] = 1;
        for (int len = 1, sum = 1; len <= height; len++, sum += len)
            for (int i = min(green, sum); i >= len; i--)
                cnt[i] = (cnt[i] + cnt[i - len]) % mod;

        int sum = (height * (height + 1)) / 2;
        long ans = 0;
        for (int i = max(0, sum - red); i <= min(green, sum); i++)
            ans = (ans + cnt[i]) % mod;
        out.println(ans);
    }

    class FastScanner {
        StringTokenizer st;
        BufferedReader br;

        FastScanner(InputStream s) {
            br = new BufferedReader(new InputStreamReader(s));
        }

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

        boolean hasNext() throws IOException {
            return br.ready() || (st != null && st.hasMoreTokens());
        }

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

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

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

        String nextLine() throws IOException {
            return br.readLine();
        }

        boolean hasNextLine() throws IOException {
            return br.ready();
        }
    }

    private void run() throws IOException {
        in = new FastScanner(System.in); // new FastScanner(new FileInputStream(".in"));
        out = new PrintWriter(System.out); // new PrintWriter(new FileOutputStream(".out"));

        solve();

        out.flush();
        out.close();
    }

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

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

public class C20141016RedGreen {
    public static void main(String args[]) throws IOException{
        PrintWriter out = new PrintWriter(System.out);
        out.println(f());
        out.close();
        System.exit(0);
    }
    public static int f() throws IOException{
        int BIG = 1000 * 1000 * 1000 + 7;
        BufferedReader f= new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(f.readLine());
        int r = Integer.parseInt(st.nextToken());
        int g = Integer.parseInt(st.nextToken());
        int h = 1;
        while (h * (h + 1) / 2 <= r + g)
            h ++;
        h --;
        int[] dp = new int[(h * (h + 1) / 2 + 1)];
        dp[0] = 1;
        for(int i = 1; i <= h; i++)
            for(int j = dp.length - 1; j >= i; j--)
                dp[j] = (dp[j - i] + dp[j]) % BIG;
        int sum = 0;
        for(int i = Math.max(dp.length - 1 - g, 0); i < Math.min(dp.length, r + 1); i++)
            sum = (sum + dp[i]) % BIG;
        return sum;
    }
}

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

public class _478D {

    public static void main(String[] args) throws Exception {
        Reader.init(System.in);
        BufferedWriter cout = new BufferedWriter(new OutputStreamWriter(System.out));

        int r = Reader.nextInt();
        int g = Reader.nextInt();
        int h = 0;
        for (h = 0; (long) (1 + h) * h / 2 <= r + g; h++) ;
        h--;

        int total = (1 + h) * h / 2;
        final int MOD = 1000000007;
        int[] f = new int[r + 1];
        f[0] = 1;

        for (int i = 1; i <= h; i++)
            for (int j = r; j >= i; j--) {
                f[j] = f[j] + f[j - i];
                if (f[j] >= MOD) f[j] -= MOD;
            }

        int ans = 0;
        for (int i = 0; i <= r; i++)
            if (total - i <= g) ans = (ans + f[i]) % MOD;
        System.out.println(ans);

        cout.close();
    }

    static class Pair<U extends Comparable<U>, V extends Comparable<V>> implements Comparable<Pair<U, V>> {
        final U _1;
        final V _2;

        private Pair(U key, V val) {
            this._1 = key;
            this._2 = val;
        }

        public static <U extends Comparable<U>, V extends Comparable<V>> Pair<U, V> instanceOf(U _1, V _2) {
            return new Pair<U, V>(_1, _2);
        }

        @Override
        public String toString() {
            return _1 + " " + _2;
        }

        @Override
        public int hashCode() {
            int res = 17;
            res = res * 31 + _1.hashCode();
            res = res * 31 + _2.hashCode();
            return res;
        }

        @Override
        public int compareTo(Pair<U, V> that) {
            int res = this._1.compareTo(that._1);
            if (res < 0 || res > 0) return res;
            else return this._2.compareTo(that._2);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (!(obj instanceof Pair)) return false;
            Pair<?, ?> that = (Pair<?, ?>) obj;
            return _1.equals(that._1) && _2.equals(that._2);
        }
    }

    /**
     * Class for buffered reading int and double values
     */
    static class Reader {
        static BufferedReader reader;
        static StringTokenizer tokenizer;

        /**
         * call this method to initialize reader for InputStream
         */
        static void init(InputStream input) {
            reader = new BufferedReader(new InputStreamReader(input));
            tokenizer = new StringTokenizer("");
        }

        /**
         * get next word
         */
        static String next() throws IOException {
            while (!tokenizer.hasMoreTokens()) {
                // TODO add check for eof if necessary
                tokenizer = new StringTokenizer(reader.readLine());
            }
            return tokenizer.nextToken();
        }

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

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

    static class ArrayUtil {
        static void swap(int[] a, int i, int j) {
            int tmp = a[i];
            a[i] = a[j];
            a[j] = tmp;
        }

        static void swap(long[] a, int i, int j) {
            long tmp = a[i];
            a[i] = a[j];
            a[j] = tmp;
        }

        static void swap(double[] a, int i, int j) {
            double tmp = a[i];
            a[i] = a[j];
            a[j] = tmp;
        }

        static void swap(char[] a, int i, int j) {
            char tmp = a[i];
            a[i] = a[j];
            a[j] = tmp;
        }

        static void swap(boolean[] a, int i, int j) {
            boolean tmp = a[i];
            a[i] = a[j];
            a[j] = tmp;
        }

        static void reverse(int[] a, int i, int j) {
            for (; i < j; i++, j--)
                swap(a, i, j);
        }

        static void reverse(long[] a, int i, int j) {
            for (; i < j; i++, j--)
                swap(a, i, j);
        }

        static void reverse(double[] a, int i, int j) {
            for (; i < j; i++, j--)
                swap(a, i, j);
        }

        static void reverse(char[] a, int i, int j) {
            for (; i < j; i++, j--)
                swap(a, i, j);
        }

        static void reverse(boolean[] a, int i, int j) {
            for (; i < j; i++, j--)
                swap(a, i, j);
        }

        static long sum(int[] a) {
            int sum = 0;
            for (int i : a)
                sum += i;
            return sum;
        }

        static long sum(long[] a) {
            long sum = 0;
            for (long i : a)
                sum += i;
            return sum;
        }

        static double sum(double[] a) {
            double sum = 0;
            for (double i : a)
                sum += i;
            return sum;
        }

        static int max(int[] a) {
            int max = Integer.MIN_VALUE;
            for (int i : a)
                if (i > max) max = i;
            return max;
        }

        static int min(int[] a) {
            int min = Integer.MAX_VALUE;
            for (int i : a)
                if (i < min) min = i;
            return min;
        }

        static long max(long[] a) {
            long max = Long.MIN_VALUE;
            for (long i : a)
                if (i > max) max = i;
            return max;
        }

        static long min(long[] a) {
            long min = Long.MAX_VALUE;
            for (long i : a)
                if (i < min) min = i;
            return min;
        }
    }
}

import java.util.Scanner;

public class RedGreenTowers {
	public static int MOD = (int) (1e9 + 7);

	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int R = scan.nextInt();
		int G = scan.nextInt();
		int H = 0;
		for (int i = 1; i <= 1000; i++)
			if ((i * (i + 1) / 2) > R + G) {
				H = i - 1;
				break;
			}
		long[] dp = new long[R + 1];
		dp[0] = 1;
		for (int i = 1; i <= H; i++)
			for (int j = R - i; j >= 0; j--) {
				dp[j + i] += dp[j];
				if (dp[j + i] >= MOD)
					dp[j + i] -= MOD;
			}

		long answer = 0;
		for (int i = 0; i <= R; i++) {
			if (H * (H + 1) / 2 - i <= G)
				answer += dp[i];
		}
		System.out.println(answer % MOD);
		scan.close();

	}
}

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

public class D_RedGreenTowers {

	static int M = (int) (2 * Math.pow(10, 5)) + 1, N = 633;
	static int mod = (int) (1e9 + 7);
	static int R, G, H;
	static int dp[][] = new int[2][M];

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

		R = sc.nextInt(); G = sc.nextInt();
		int total = R + G;
		H = 1; total -= 1;
		int i = 2;
		while(total >= i) {
			total -= i;
			i++; H++;
		}
		out.println(solve());

		out.flush();
		out.close();
	}

//	private static int solve(int level, int r, int g) {
//		if(level == H + 1) return 1;
//		if(r < level && g < level) return 0;
//		if(memo[level][r] != -1) return memo[level][r];
//
//		int ways = 0;
//		if(g >= level)
//			ways += solve(level + 1, r, g - level);
//		if(r >= level)
//			ways += solve(level + 1, r - level, g);
//		return memo[level][r] = ways % mod;
//	}

	private static int solve() {
		dp[0][R] = 1; int total = R + G;
		int curr = 0, blocks = 0;
		for(int i = 0; i < H; ++i) {
			blocks += i;
			for(int reds = R; reds >= 0; reds--) {
				int greens = total - blocks - reds;
				if(dp[curr][reds] != 0) {
					if(reds >= (i + 1))
						dp[1 - curr][reds - (i + 1)] = (dp[1 - curr][reds - (i + 1)] + dp[curr][reds]) % mod;
					if(greens >= (i + 1)) dp[1 - curr][reds] = (dp[curr][reds] + dp[1 - curr][reds]) % mod;
				}
				dp[curr][reds] = 0;
			}
			curr = 1 - curr;
		}
		int res = 0;
		for(int i = 0; i <= R; ++i) res = (dp[curr][i] + res) % mod;
		return res;
	}

	static class Scanner{
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}

		public Scanner(FileReader r){	br = new BufferedReader(r);}

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

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

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

		public String nextLine() throws IOException {return br.readLine();}

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

		public boolean ready() throws IOException {return br.ready();}
	}
}

import java.io.*;
import java.util.*;
/*
 * 	Heart beats fast
 * 		Colors and promises
 * 			How to be brave
 * 				How can I love when I am afraid to fall...
 */
//read the question correctly (is y a vowel? what are the exact constraints?)
//look out for SPECIAL CASES (n=1?) and overflow (ll vs int?)
public class Main
{
	public static void main(String[] args)
	{
		int red=ni(),green=ni();
		int r=Math.min(red, green),g=Math.max(red, green);
	    int dp[][]=new int[2][r+1];
		dp[0][r]=1;
		int[]te;
		int h=(int)Math.sqrt(1+8*(r+g))/2;
		for(int i=0; i<h; i++)
		{
		    int tem=Math.min(r,g-1-i+r-(i*(i+1))/2);
			for(int j=0; j<=tem; j++)
				dp[1][j]=dp[0][j];
			for(int j=i+1; j<=r; j++)
				dp[1][j-i-1]=(dp[1][j-i-1]+dp[0][j])%mod;
			long sum=0;
			for(int j=0; j<=r; j++)
				sum+=dp[1][j];
			if(sum==0)
				break;
			te=dp[0];
			dp[0]=dp[1];
			dp[1]=te;
 			Arrays.fill(dp[1],0);
		}
		long ans=0;
		for(int i:dp[0])
			ans=(ans+i);
		pr(ans%mod);
		System.out.print(output);
	}
	///////////////////////////////////////////
	///////////////////////////////////////////
	///template from here
	static final int mod=1000000007;
	static final double eps=1e-8;
	static final long inf=100000000000000000L;
	static Reader in=new Reader();
	static StringBuilder output=new StringBuilder();
	static Random rn=new Random();
	//output functions////////////////
	static void pr(Object a){output.append(a+"\n");}
	static void pr(){output.append("\n");}
	static void p(Object a){output.append(a);}
	static void pra(int[]a){for(int i:a)output.append(i+" ");output.append("\n");}
	static void pra(long[]a){for(long i:a)output.append(i+" ");output.append("\n");}
	static void pra(String[]a){for(String i:a)output.append(i+" ");output.append("\n");}
	static void pra(double[]a){for(double i:a)output.append(i+" ");output.append("\n");}
	static void sop(Object a){System.out.println(a);}
	static void flush(){System.out.println(output);output=new StringBuilder();}
	//////////////////////////////////
	//input functions/////////////////
	static int ni(){return in.nextInt();}
	static long nl(){return Long.parseLong(in.next());}
	static String ns(){return in.next();}
	static double nd(){return Double.parseDouble(in.next());}
	static int[] nia(int n){int a[]=new int[n];for(int i=0; i<n; i++)a[i]=ni();return a;}
	static int[] pnia(int n){int a[]=new int[n+1];for(int i=1; i<=n; i++)a[i]=ni();return a;}
	static long[] nla(int n){long a[]=new long[n];for(int i=0; i<n; i++)a[i]=nl();return a;}
	static String[] nsa(int n){String a[]=new String[n];for(int i=0; i<n; i++)a[i]=ns();return a;}
	static double[] nda(int n){double a[]=new double[n];for(int i=0; i<n; i++)a[i]=nd();return a;}
	//////////////////////////////////
	//some utility functions
	static void exit(){System.exit(0);}
	static void psort(int[][] a)
	{
		Arrays.sort(a, new Comparator<int[]>()
		{
			@Override
			public int compare(int[]a,int[]b)
			{
				if(a[0]>b[0])
					return 1;
				else if(b[0]>a[0])
					return -1;
				return 0;
			}
		});
	}
	static String pr(String a, long b)
	{
		String c="";
		while(b>0)
		{
			if(b%2==1)
				c=c.concat(a);
			a=a.concat(a);
			b>>=1;
		}
		return c;
	}
	static long powm(long a, long b, long m)
	{
		long an=1;
		long c=a;
		while(b>0)
		{
			if(b%2==1)
				an=(an*c)%m;
			c=(c*c)%m;
			b>>=1;
		}
		return an;
	}
	static int gcd(int a, int b)
	{
		if(b==0)
			return a;
		else
			return gcd(b, a%b);
	}
	/////////////////////////
	static class Reader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;
        public Reader() {
            reader = new BufferedReader(new InputStreamReader(System.in), 32768);
            tokenizer = null;
        }
        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }
        public long nextLong() {
        	return Long.parseLong(next());
        }
        public double nextDouble() {
        	return Double.parseDouble(next());
        }
    }
}

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

public class Main {
    private final Reader reader;

    private final Writer writer;

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

    }

    private void solve() throws IOException {
        int MOD = 1000000007;
        int R = reader.nextUnsignedInt();
        int G = reader.nextUnsignedInt();
        int H_MAX = 0;
        for (int h = 1; h < 10000; h++) {
            if ((h * (h + 1) / 2) > R + G) {
                H_MAX = h - 1;
                break;
            }
        }

        //dp[t][r] = dp[t-1][r-t] + dp[t-1][r];
        //dp[t][r] = number of towers of highest possible height H_MAX,
        //           that have t upper floor already coloured and we
        //           have used r red blocks to do so
        //answer will be dp[H_MAX][R];
        //
        int dp[][] = new int[2][R + 1];
        dp[0][0] = 1;

        for (int t = 1; t <= H_MAX; t++) {
            int now = t&1;
            int last = now^1;
            int coloured_blocks = t * (t - 1) / 2;
            for (int r = 0; r <= R; r++) {
                int redUsed = r;
                int greenUsed = coloured_blocks - redUsed;
                int greenRemaining = G - greenUsed;

                dp[now][r] = (r >= t && r <= (coloured_blocks + t) ? dp[last][r - t] : 0) //painting t level with t red blocks
                        + (greenRemaining >= t ? dp[last][r] : 0); // painting t level with t green blocks

                if (dp[now][r] >= MOD) {
                    dp[now][r] -= MOD;
                }
            }
        }

        int ans = 0;
        for (int r = 0; r <= R; r++) {
            ans = ans + dp[H_MAX&1][r];
            if (ans >= MOD) {
                ans -= MOD;
            }
        }
        writer.print(ans + "\n");
        writer.flush();
    }

    Main(InputStream in, OutputStream out) {
        this.reader = new Reader(in);
        this.writer = new Writer(out);
    }

    public Main() {
        this.reader = new Reader();
        this.writer = new Writer();
    }

}

class Reader {

    private final int BUFFER_SIZE = 65536;

    private final DataInputStream din;

    private final byte[] buffer;

    private int bufferPointer, bytesRead;

    Reader() {
        din = new DataInputStream(System.in);
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public Reader(InputStream in) {
        din = new DataInputStream(in);
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public long nextUnsignedLong() throws IOException {
        long ret = 0;
        byte c = read();
        while (c <= 32) c = read();
        do {
            ret = ret * 10 + c - '0';
        } while ((c = read()) >= '0');
        return ret;
    }

    public int nextUnsignedInt() throws IOException {
        int ret = 0;
        byte c = read();
        while (c <= 32) c = read();
        do {
            ret = ret * 10 + c - '0';
        } while ((c = read()) >= '0');
        return ret;
    }

    public int nextInt() throws IOException {
        int ret = 0;
        byte c = read();
        while (c <= ' ') c = read();
        boolean neg = (c == '-');
        if (neg) {
            c = read();
        }
        do {
            ret = ret * 10 + c - '0';
        } while ((c = read()) >= '0');
        if (neg) {
            return -ret;
        }
        return ret;
    }

    public String nextString(int MAX) throws IOException {
        int cnt = 0;
        char[] buf = new char[MAX];
        byte c;
        while ((c = read()) < 33) ;
        buf[cnt++] = (char) c;
        while ((c = read()) >= 33) {
            buf[cnt++] = (char) c;
        }
        return new String(buf, 0, cnt);
    }

    public char firstCharOfNextUnSpacedString() throws IOException {
        byte c;
        char res;
        while ((c = read()) < 33) ;
        res = (char) c;
        while ((c = read()) >= 33) ;
        return res;
    }

    private void fillBuffer() throws IOException {
        bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
        if (bytesRead == -1) {
            buffer[0] = -1;
        }
    }

    private byte read() throws IOException {
        if (bufferPointer == bytesRead) {
            fillBuffer();
        }
        return buffer[bufferPointer++];
    }
}

class Writer {
    private final BufferedWriter out;

    Writer() {
        out = new BufferedWriter(new OutputStreamWriter(System.out), 512);
    }

    public Writer(OutputStream out) {
        this.out = new BufferedWriter(new OutputStreamWriter(out), 512);
    }

    void print(char c) throws IOException {
        out.write(c);
    }

    void print(String str) throws IOException {
        out.write(str);
    }

    void println() throws IOException {
        out.write("\n");
    }

    void flush() throws IOException {
        out.flush();
    }

    @Override
    protected void finalize() throws IOException {
        out.flush();
    }
}

import java.io.*;
import java.util.Locale;
import java.util.StringTokenizer;

public class A implements Runnable {

    private static final boolean ONLINE_JUDGE = System.getProperty("ONLINE_JUDGE") != null;

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

    private void init() throws FileNotFoundException {
        Locale.setDefault(Locale.US);
        String fileName = "";
        if (ONLINE_JUDGE && fileName.isEmpty()) {
            in = new BufferedReader(new InputStreamReader(System.in));
            out = new PrintWriter(System.out);
        } else {
            if (fileName.isEmpty()) {
                in = new BufferedReader(new FileReader("input.txt"));
                out = new PrintWriter("output.txt");
            } else {
                in = new BufferedReader(new FileReader(fileName + ".in"));
                out = new PrintWriter(fileName + ".out");
            }
        }
    }

    String readString() {
        while (!tok.hasMoreTokens()) {
            try {
                tok = new StringTokenizer(in.readLine());
            } catch (Exception e) {
                return null;
            }
        }
        return tok.nextToken();
    }

    int readInt() {
        return Integer.parseInt(readString());
    }

    long readLong() {
        return Long.parseLong(readString());
    }

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

    int[] readIntArray(int size) {
        int[] a = new int[size];
        for (int i = 0; i < size; i++) {
            a[i] = readInt();
        }
        return a;
    }

    public static void main(String[] args) {
        //new Thread(null, new _Solution(), "", 128 * (1L << 20)).start();
        new A().run();
    }

    long timeBegin, timeEnd;

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

    @Override
    public void run() {
        try {
            timeBegin = System.currentTimeMillis();
            init();
            solve();
            out.close();
            time();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }
    }

    private int aiverson(boolean good) {
        return good ? 1 : 0;
    }

    private void solve() {
        int g = readInt();
        int r = readInt();
        int maxH = 1;
        int left = 1, right = r + g;
        while (left <= right) {
            int mid = (left + right) >> 1;
            if (1l * mid * (mid + 1) / 2 <= r + g) {
                maxH = mid;
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }

        int[][] dp = new int[2][r + 1];
        dp[0][0] = 1;
        for (int level = 1; level <= maxH; level++) {
            int cur = level % 2;
            for (int spentRed = 0; spentRed <= Math.min(r, level * (level + 1) / 2); spentRed++) {
                dp[cur][spentRed] = 0;
                if (spentRed - level >= 0) {
                    dp[cur][spentRed] += dp[1 - cur][spentRed - level];
                }
                int spentGreen = level * (level + 1) / 2 - spentRed;
                if (spentGreen >= 0 && spentGreen <= g && spentGreen - level >= 0) {
                    dp[cur][spentRed] += dp[1 - cur][spentRed];
                }
                dp[cur][spentRed] %= mod;
            }
        }

        int answer = 0;
        for (int count : dp[maxH % 2]) {
            answer = (answer + count) % mod;
        }

        out.println(answer);
    }

    final int mod = 1000 * 1000 * 1000 + 7;
}

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

public class D {

    final static int MOD = 1000000007;

    void solve() throws IOException {
        in = new InputReader("__std");
        out = new OutputWriter("__std");

        int r = in.readInt();
        int g = in.readInt();
        int[][] d = new int[2][r + 1];
        d[0][0] = 1;
        int k = 0;
        int c = 0;
        boolean flag = true;
        for (int h = 1; flag; ++h) {
            flag = false;
            for (int pr = 0; pr <= r; ++pr) {
                if (pr + h <= r && c - pr <= g) {
                    d[1 - k][pr + h] += d[k][pr];
                    flag = true;
                }
                int pg = c - pr;
                if (pg + h <= g && c - pg <= r) {
                    d[1 - k][pr] += d[k][pr];
                    if (d[1 - k][pr] >= MOD) d[1 - k][pr] -= MOD;
                    flag = true;
                }
            }
            if (flag) {
                Arrays.fill(d[k], 0);
                k = 1 - k;
                c += h;
            }
        }
        int res = 0;
        for (int cr = 0; cr <= r; ++cr) {
            res += d[k][cr];
            if (res >= MOD) res -= MOD;
        }
        out.println(res);

        exit();
    }

    void exit() {
        //System.err.println((System.currentTimeMillis() - startTime) + " ms");
        out.close();
        System.exit(0);
    }

    InputReader in;
    OutputWriter out;

    //long startTime = System.currentTimeMillis();

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

    class InputReader {

        private InputStream stream;

        private byte[] buffer = new byte[1024];
        private int pos, len;

        private int cur;

        private StringBuilder sb = new StringBuilder(32);

        InputReader(String name) throws IOException {
            if (name.equals("__std")) {
                stream = System.in;
            } else {
                stream = new FileInputStream(name);
            }
            cur = read();
        }

        private int read() throws IOException {
            if (len == -1) {
                throw new EOFException();
            }
            if (pos >= len) {
                pos = 0;
                len = stream.read(buffer);
                if (len == -1) return -1;
            }
            return buffer[pos++];
        }

        char readChar() throws IOException {
            if (cur == -1) {
                throw new EOFException();
            }
            char res = (char) cur;
            cur = read();
            return res;
        }

        int readInt() throws IOException {
            if (cur == -1) {
                throw new EOFException();
            }
            while (whitespace()) {
                cur = read();
            }
            if (cur == -1) {
                throw new EOFException();
            }
            int sign = 1;
            if (cur == '-') {
                sign = -1;
                cur = read();
            }
            int res = 0;
            while (!whitespace()) {
                if (cur < '0' || cur > '9') {
                    throw new NumberFormatException();
                }
                res *= 10;
                res += cur - '0';
                cur = read();
            }
            return res * sign;
        }

        long readLong() throws IOException {
            if (cur == -1) {
                throw new EOFException();
            }
            return Long.parseLong(readToken());
        }

        double readDouble() throws IOException {
            if (cur == -1) {
                throw new EOFException();
            }
            return Double.parseDouble(readToken());
        }

        String readLine() throws IOException {
            if (cur == -1) {
                throw new EOFException();
            }
            sb.setLength(0);
            while (cur != -1 && cur != '\r' && cur != '\n') {
                sb.append((char) cur);
                cur = read();
            }
            if (cur == '\r') {
                cur = read();
            }
            if (cur == '\n') {
                cur = read();
            }
            return sb.toString();
        }

        String readToken() throws IOException {
            if (cur == -1) {
                throw new EOFException();
            }
            while (whitespace()) {
                cur = read();
            }
            if (cur == -1) {
                throw new EOFException();
            }
            sb.setLength(0);
            while (!whitespace()) {
                sb.append((char) cur);
                cur = read();
            }
            return sb.toString();
        }

        boolean whitespace() {
            return cur == ' ' || cur == '\t' || cur == '\r' || cur == '\n' || cur == -1;
        }

        boolean eof() {
            return cur == -1;
        }
    }

    class OutputWriter {

        private PrintWriter writer;

        OutputWriter(String name) throws IOException {
            if (name.equals("__std")) {
                writer = new PrintWriter(System.out);
            } else {
                writer = new PrintWriter(name);
            }
        }

        void print(String format, Object ... args) {
            writer.print(new Formatter(Locale.US).format(format, args));
        }

        void println(String format, Object ... args) {
            writer.println(new Formatter(Locale.US).format(format, args));
        }

        void print(Object value) {
            writer.print(value);
        }

        void println(Object value) {
            writer.println(value);
        }

        void println() {
            writer.println();
        }

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

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

public class Red_GreenTowers478D {
    static int P = (int) 1e9 + 7;

    static void go() {
        int r = in.nextInt();
        int g = in.nextInt();

        if (r > g) {
            int temp = r;
            r = g;
            g = temp;
        }

        int[] dp = new int[r + 1];
        dp[0] = 1;
        int maxH = 1;
        int up = 0;
        while (maxH * (maxH + 1) / 2 <= r + g) {
            up = Math.min(r, up + maxH);
            for (int i = up; i >= maxH; i--) {
                dp[i] += dp[i - maxH];
                if (dp[i] > P)
                    dp[i] -= P;
            }
            maxH++;
        }
        maxH--;
        int total = 0;
        //int sum = maxH * (maxH + 1) / 2;
        for (int i = Math.max(maxH * (maxH + 1) / 2 - g, 0); i <= r && dp[i] > 0; i++) {
            total += dp[i];
            if (total > P)
                total -= P;
        }

        out.println(total);
    }

    static InputReader in;
    static PrintWriter out;

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

        go();

        out.close();
    }

    static class InputReader {
        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[] nextIntArray(int len) {
            int[] ret = new int[len];
            for (int i = 0; i < len; i++)
                ret[i] = nextInt();
            return ret;
        }

        public long[] nextLongArray(int len) {
            long[] ret = new long[len];
            for (int i = 0; i < len; i++)
                ret[i] = nextLong();
            return ret;
        }

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

        public long nextLong() {
            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 String nextString() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            StringBuilder sb = new StringBuilder(1024);
            do {
                sb.append((char) c);
                c = read();
            } while (!isSpaceChar(c));
            return sb.toString();
        }

        public static boolean isSpaceChar(int c) {
            switch (c) {
                case -1:
                case ' ':
                case '\n':
                case '\r':
                case '\t':
                    return true;
                default:
                    return false;
            }
        }
    }
}

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.PrintWriter;
import java.util.Scanner;
import static java.lang.Math.*;

public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner cin = new Scanner(new BufferedInputStream(System.in));
        PrintWriter cout = new PrintWriter(new BufferedOutputStream(System.out));
        Task.solve(cin, cout);
        cout.flush();
    }

}
class Task{
    static Scanner cin;
    static PrintWriter cout;
    final static int maxn = 400005;
    final static int MOD = 1000000007;
    static int []dp = new int[maxn];
    static int r, g;
    static int GetHeight(){
        for (int i = 1; ; i++){
            if (i * (i + 1) / 2 > r + g){
                return i-1;
            }
        }
    }
    public static void solve(Scanner cin, PrintWriter cout){
        r = cin.nextInt();
        g = cin.nextInt();
        int h = GetHeight();
        int res = 0;
        dp[0] = 1;
        for (int i = 1; i <= h; i++){
            for (int j = r; j >= 0; j--){
                dp[i+j] = (dp[i+j] + dp[j]) % MOD;
            }
        }
        for (int i = max(h*(h+1)/2 - g, 0); i <= r; i++){
            res = (res + dp[i]) % MOD;
        }
        cout.println(res);
    }
}

import java.util.*;

public class D {
	public static void main (String[] args) {
	    Scanner fs = new Scanner(System.in);

		//the time limit is way too strict for this problem
		//should be 3 sec if the intended solution complexity
		//is O(max * min(red, green))

		int red = fs.nextInt();
		int green = fs.nextInt();
		int max = bs(red, green);
//		while((max+1) * (max+2) / 2 <= red + green) max++;

		if(green < red) {
			int t = green;
			green = red;
			red = t;
		}

		int[] dp = new int[red+1];
		dp[0] = 1;
		long res = 0, mod = (int)1e9+7;
		for(int h = 1; h <= max; h++) {
			for(int r = Math.min(red, (h * (h+1))/2); r >= h; r--) {
				if(r-h < 0) break;
				dp[r] = (dp[r] + dp[r-h]);
				if(dp[r] >= mod) dp[r] -= mod;
			}
//			int index = h&1;
//			for(int r = 0; r <= red; r++) {
				//number of ways to build a tower with height h
				//and r red blocks.
//				dp[index][r] = 0;
//				int numGreens = h * (h+1) / 2 - r;
//				if(r - h >= 0) {
					//if I can at least build the bottom level
					//then the number of ways I can build a tower
					//with h-1 and r-h reds
//					dp[index][r] = (dp[index][r] + dp[index^1][r-h]);
//					if(dp[index][r] >= mod) dp[index][r] -= mod;
//				}
//
//				if(numGreens >= 0 && numGreens <= green) {
					//if the number of greens I need to complete this tower
					//is within the number of greens I have, then the number
					//of ways I can make a tower with r reds at level h
					//is just the number of ways I can make a tower with
					//r reds at level h-1 (since green is handling the rest)
//					dp[index][r] = (dp[index][r] + dp[index^1][r]);
//					if(dp[index][r] >= mod) dp[index][r] -= mod;
//				}
//			}
		}

		for(int i = 0; i <= red && i <= (max*max+max)/2; i++) {
			int take = (max*max+max)/2 - i;
			if(take <= green)
				res += dp[i];
		}
		res %= mod;
		System.out.println(res);
	}

	static int bs (int red, int green) {
		int res = 0;
		int lo = 1, hi = 895;
		for(int bs = 0; bs < 50 && lo <= hi; bs++) {
			int mid = (lo + hi) >> 1;
			int x = (mid+1)*(mid+2) / 2;
			if(x <= red+green) {
				res = Math.max(res, mid);
				lo = mid+1;
			}
			else {
				hi = mid-1;
			}
		}
		return ++res;
	}

}

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

public class cf273D {
	static int mod = 1000000007;
    public static void main(String[] args) throws Exception {
    	// BufferedReader in = new BufferedReader(new FileReader("cf273D.in"));
    	BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

		String str = in.readLine();
		int r = Integer.parseInt(str.substring(0, str.indexOf(" ")));
		int g = Integer.parseInt(str.substring(str.indexOf(" ") + 1));

		int h = 1;
		while((h + 1) * (h + 2) / 2 <= r + g) {
			h++;
		}
		int max = h * (h + 1) / 2;
		long[] greens = new long[g + 1];
		greens[0] = 1;
		for(int i = 1; i <= h; i++) {
			int size = Math.min(g, i * (i + 1) / 2);
			int min = Math.max(i, Math.min(size - r, g - max + size));
			for(int j = size; j >= min; j--) {
				greens[j] += greens[j - i];
				if(greens[j] >= mod) {
					greens[j] -= mod;
				}
			}
		}
		long total = 0;
		for(int i = Math.max(0, max - r); i <= g; i++) {
			total += greens[i];
			total %= mod;
		}
		System.out.println(total);
	}
}

import static java.lang.Math.*;

public class D {

	public D () {
		int A = sc.nextInt(), B = sc.nextInt();

		int N = -1, S = A+B;
		for (int i : rep(1000))
			if (i*(i+1) <= 2*S)
				N = i;
		int Z = N*(N+1)/2;

		int [] P = new int [A+1]; P[0] = 1;
		for (int i : req(1, N))
			for (int j = A; j >= i; --j)
				P[j] = (P[j] + P[j-i]) % MOD;

		int res = 0;
		for (int i : req(max(Z-B,0), A))
			res = (res + P[i]) % MOD;
		exit(res);
	}

	private static final int MOD = (int) 1e9 + 7;
	private static int [] rep(int N) { return rep(0, N); }
	private static int [] rep(int S, int T) { if (T <= S) return new int [0]; int [] res = new int [T-S]; for (int i = S; i < T; ++i) res[i-S] = i; return res; }
	private static int [] req(int S, int T) { return rep(S, T+1); }
	////////////////////////////////////////////////////////////////////////////////////
	private final static IOUtils.MyScanner sc = new IOUtils.MyScanner();
	private static void exit (Object o, Object ... A) { IOUtils.print(o, A); IOUtils.exit(); }
	private static class IOUtils {
		public static class MyScanner {
			public String next() { newLine(); return line[index++]; }
			public int nextInt() { return Integer.parseInt(next()); }
			//////////////////////////////////////////////
			private boolean eol() { return index == line.length; }
			private String readLine() {
				try {
					return r.readLine();
				} catch (Exception e) {
					throw new Error (e);
				}
			}
			private final java.io.BufferedReader r;
			private MyScanner () { this(new java.io.BufferedReader(new java.io.InputStreamReader(System.in))); }
			private MyScanner (java.io.BufferedReader r) {
				try {
					this.r = r;
					while (!r.ready())
						Thread.sleep(1);
					start();
				} catch (Exception e) {
					throw new Error(e);
				}
			}
			private String [] line;
			private int index;
			private void newLine() {
				if (line == null || eol()) {
					line = split(readLine());
					index = 0;
				}
			}
			private String [] split(String s) { return s.length() > 0 ? s.split(" ") : new String [0]; }
		}
		private static String build(Object o, Object ... A) { return buildDelim(" ", o, A); }
		private static String buildDelim(String delim, Object o, Object ... A) {
			StringBuilder b = new StringBuilder();
			append(b, o, delim);
			for (Object p : A)
				append(b, p, delim);
			return b.substring(delim.length());
		}
		//////////////////////////////////////////////////////////////////////////////////
		private static void start() { if (t == 0) t = millis(); }
		private static void append(StringBuilder b, Object o, String delim) {
			if (o.getClass().isArray()) {
				int len = java.lang.reflect.Array.getLength(o);
				for (int i = 0; i < len; ++i)
					append(b, java.lang.reflect.Array.get(o, i), delim);
			} else if (o instanceof Iterable<?>)
				for (Object p : (Iterable<?>) o)
					append(b, p, delim);
			else {
				if (o instanceof Double)
					o = new java.text.DecimalFormat("#.############").format(o);
				b.append(delim).append(o);
			}
		}
		private static java.io.PrintWriter pw = new java.io.PrintWriter(System.out);
		private static void print(Object o, Object ... A) { pw.println(build(o, A)); }
		private static void err(Object o, Object ... A) { System.err.println(build(o, A)); }
		private static void exit() {
			IOUtils.pw.close();
			System.out.flush();
			err("------------------");
			err(IOUtils.time());
			System.exit(0);
		}
		private static long t;
		private static long millis() { return System.currentTimeMillis(); }
		private static String time() { return "Time: " + (millis() - t) / 1000.0; }
	}
	public static void main (String[] args) { new D(); IOUtils.exit(); }
}

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

public class L {

	static int mod = (int) (1e9 + 7);

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

		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		int h = maxl(n, m);
		int[][] a = new int[2][n + 1];
		a[0][n] = 1;
		int cur = 0;
		for (int i = 1; i <= h; i++) {
			Arrays.fill(a[cur ^ 1], 0);
			for (int j = 0; j < n + 1; j++) {
				if (a[cur][j] == 0)
					continue;
				int g = m - (i - 1) * i / 2 + (n - j);
				if (j >= i) {
					a[cur ^ 1][j - i] += a[cur][j] % mod;
				}
				if (g >= i) {
					a[cur ^ 1][j] += a[cur][j] % mod;
				}
			}
			cur ^= 1;

		}
		long sum = 0;
		for (int i = 0; i <= n; i++) {
			sum += a[cur][i];
			sum %= mod;
		}
		System.out.println(sum);

		pw.flush();
	}

	static int maxl(int r, int g) {
		int s = 0;
		int e = 1000;
		int ans = -1;
		while (s <= e) {
			int mid = s + e >> 1;
			if (mid * (mid + 1) / 2 <= r + g) {
				ans = mid;
				s = mid + 1;
			} else
				e = mid - 1;

		}
		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.Arrays;
import java.util.StringTokenizer;

public class _22_Red_Green_Towers {

	public static void main(String[] args) throws IOException {
		Scanner scn=new Scanner(System.in);
		PrintWriter out = new PrintWriter(System.out);
		int r = scn.nextInt();
		int g = scn.nextInt();
		int h = 0;

		int sum = g + r;
		if (sum == 1) {
			h = 1;
		}

		while (sum >= h) {
			sum -= h++;
		}
		h--;

		int[] total = new int[h + 1];
		for (int i = 1; i < total.length; i++) {
			total[i] += total[i - 1] + i;
		}
		int[] last = new int[r + 1];
		Arrays.fill(last, 1);
		int mod = 1000000007;
		for (int i = h - 1; i >= 0; i--) {
			int[] cur = new int[r + 1];
			for (int j = 0; j <= r; j++) {
				int red = j;
				long green = g - (total[i] - (r - red));
				if (green >= (i + 1)) {
					cur[j] = (cur[j] + last[j]) % mod;
				}
				if (red >= (i + 1)) {
					cur[j] = (cur[j] + last[j - (i + 1)]) % mod;
				}

			}
			last = cur;

		}

	out.print(last[r]);
	out.flush();
	}

	static class Scanner

	{
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}

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

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

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

		public String nextLine() throws IOException {return br.readLine();}

		public double nextDouble() throws IOException
		{
			String x = next();
			StringBuilder sb = new StringBuilder("0");
			double res = 0, f = 1;
			boolean dec = false, neg = false;
			int start = 0;
			if(x.charAt(0) == '-')
			{
				neg = true;
				start++;
			}
			for(int i = start; i < x.length(); i++)
				if(x.charAt(i) == '.')
				{
					res = Long.parseLong(sb.toString());
					sb = new StringBuilder("0");
					dec = true;
				}
				else
				{
					sb.append(x.charAt(i));
					if(dec)
						f *= 10;
				}
			res += Long.parseLong(sb.toString()) / f;
			return res * (neg?-1:1);
		}

		public boolean ready() throws IOException {return br.ready();}

	}
}

/**
 * ******* Created  on 25/12/19 8:47 AM*******
 */

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

public class D478 implements Runnable {

    private static final int MAX = 2*(int) (1E5 + 5);
    private static final int MOD = (int) (1E9 + 7);
    private static final long Inf = (long) (1E14 + 10);

    private void solve() throws IOException {
        int r =reader.nextInt();
        int g =reader.nextInt();
        if(r > g)
            r = swap(g, g=r);
        int n = r+g;
        int h = 0;
        while(true ){
            int sum = h*(h+1)/2;
            if(sum > n)break;
            h++;
        }
        h--;
        int ex = (n) - (h*(h+1))/2;
        int[][] dp = new int[2][MAX];
        dp[0][0] =1;
        int cur=0 , prev =1;
        for(int i =1;i<=h;i++){
            int sum = Math.min((i*(i+1))/2, MAX-1 );
            cur =prev;
            prev = cur==1 ?0:1;
            for(int j=0;j<=sum;j++){
                if(j<i) dp[cur][j] = dp[prev][j];
                else dp[cur][j] = (dp[prev][j] + dp[prev][j-i] ) %MOD;
            }

        }
        long ans = 0;
        for(int i=0;i<=ex && g-i>=0;i++){
            ans =(ans+ dp[cur][g-i]) %MOD;
        }
        writer.println(ans);

    }

    private int swap(int g, int i) {
        return g;
    }

    public static void main(String[] args) throws IOException {
        try (Input reader = new StandardInput(); PrintWriter writer = new PrintWriter(System.out)) {
            new D478().run();
        }
    }

    StandardInput reader;
    PrintWriter writer;

    @Override
    public void run() {
        try {
            reader = new StandardInput();
            writer = new PrintWriter(System.out);
            solve();
            reader.close();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    interface Input extends Closeable {
        String next() throws IOException;

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

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

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

        default int[] readIntArray() throws IOException {
            return readIntArray(nextInt());
        }

        default int[] readIntArray(int size) throws IOException {
            int[] array = new int[size];
            for (int i = 0; i < array.length; i++) {
                array[i] = nextInt();
            }
            return array;
        }

        default long[] readLongArray(int size) throws IOException {
            long[] array = new long[size];
            for (int i = 0; i < array.length; i++) {
                array[i] = nextLong();
            }
            return array;
        }
    }

    private static class StandardInput implements Input {
        private final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        private StringTokenizer stringTokenizer;

        @Override
        public void close() throws IOException {
            reader.close();
        }

        @Override
        public String next() throws IOException {
            if (stringTokenizer == null || !stringTokenizer.hasMoreTokens()) {
                stringTokenizer = new StringTokenizer(reader.readLine());
            }
            return stringTokenizer.nextToken();
        }
    }
}

import java.util.Scanner;

public class Main{

	static final int MOD = 1000000007;

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		while (in.hasNext()) {
			int r = in.nextInt(), g = in.nextInt();
			if (r > g) {
				r = r ^ g;
				g = r ^ g;
				r = r ^ g;
			}
			int h = 1, sum = r + g;
			while (sum >= 0)
				sum -= h++;
			h -= 2;
			sum = h * (h + 1) / 2;

			int dp[] = new int[r + 1];
			dp[0] = 1;
			for (int i = 1; i <= h; i++)
				for (int k = Math.min(r, i * (i + 1) / 2); k >= i; k--)
					dp[k] = (dp[k] + dp[k - i]) % MOD;
			int ans = 0;
			for (int i = Math.max(0, sum - g); i <= Math.min(sum, r); i++)
				ans = (ans + dp[i]) % MOD;
			System.out.println(ans);
		}
		in.close();
	}

}

/* package whatever; // don't place package name! */

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

/* Name of the class has to be "Main" only if the class is public. */
public class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        Scanner sc = new Scanner(System.in);
        int mod = 1000000007;
        int r = sc.nextInt();
        int g = sc.nextInt();
        int n = (int)Math.floor((Math.pow(8*(r+g)+1, 0.5)-1)/2);
        int firstdp[] = new int[n*(n+1)/2+1];
        int seconddp[] = new int[n*(n+1)/2+1];
        int temp[] = new int[n*(n+1)/2+1];
        for(int i = 0;i<=n*(n+1)/2;i++){
            firstdp[i]=0;
            seconddp[i]=0;
        }
        firstdp[0]=1;
        for(int i = 1;i<n+1;i++){
            for(int j = 0;j<i;j++){
                seconddp[j]=firstdp[j]%mod;
                temp[j]=seconddp[j];
            }
            for(int j = i;j<=i*(i+1)/2;j++){
                seconddp[j]=(firstdp[j]%mod+firstdp[j-i]%mod)%mod;
                temp[j]=seconddp[j];
            }
            for(int j = 0;j<=i*(i+1)/2;j++){
                firstdp[j]=temp[j];
            }

        /*for(int j = 0;j<=(n*(n+1))/2;j++){
                System.out.print(firstdp[j]);
            }
            System.out.println();
        for(int j = 0;j<=(n*(n+1))/2;j++){
                System.out.print(seconddp[j]);
            }
            System.out.println();*/
        }
        if(r>n*(n+1)/2){
            r=n*(n+1)/2;
        }
        if(g>n*(n+1)/2){
            g=n*(n+1)/2;
        }
        int lower = Math.max(0,n*(n+1)/2-g);
        int upper = Math.min(r,n*(n+1)/2);
        long answer = 0;
        for(int i = lower;i<=upper;i++){
            answer+=(long)(seconddp[i]%(long)mod);
            answer=answer%mod;
        }
        System.out.println(answer);
        /*System.out.println("=============");
        System.out.println(lower + " " + upper);
        System.out.println("=============");
        System.out.println(n);*/
    }
}

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

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		InputReader in = new InputReader(new InputStreamReader(System.in));
		PrintWriter out = new PrintWriter(System.out);
		new Task().go(in, out);
		out.close();
	}

}

class Task {
	public int maxn = 100010;

	public void go(InputReader in, PrintWriter out) {
        int r = in.nextInt();
        int g = in.nextInt();
        int h = 1;
        for ( ; h * (h + 1) / 2 <= r + g; ++h);
        h--;
        int[] dp = new int[r + 1];
        dp[0] = 1;
        int mod = 1000000007;
        long ret = 0;
        for (int i = 1; i <= h; ++i) {
            for (int j= r - i; j >= 0; --j) {
                dp[j + i] += dp[j];
                if (dp[j + i] >= mod) dp[j + i] -= mod;
            }
        }
        for (int j = 0; j <= r; ++j) {
            if (h * (h + 1) / 2 - j <= g) ret += dp[j];
        }
        out.println(ret % mod);
    }
}

class InputReader {
	BufferedReader bf;
	StringTokenizer st;

	InputReader(InputStreamReader is) {
		bf = new BufferedReader(is);
	}

	public String next() {
		if (st == null || !st.hasMoreElements()) {
			try {
				st = new StringTokenizer(bf.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return st.nextToken();
	}

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

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

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

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

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

	FastReader in = new FastReader();
	PrintWriter out = new PrintWriter(System.out);
	void run(){
		work();
		out.flush();
	}
	long mod=1000000007;
	long gcd(long a,long b) {
		return a==0?b:b>=a?gcd(b%a,a):gcd(b,a);
	}

	void work() {
		int n=in.nextInt(),m=in.nextInt();
		if(n>m) {
			int t=m;
			m=n;
			n=t;
		}
		int s=n+m;
		int k=(int)Math.sqrt(s*2);
		if(k*(k+1)>s*2) {
			k--;
		}
		s=(1+k)*k/2;
		long ret=0;
		k=Math.min(k, n);//最底层
		long[] dp=new long[n+1];
		dp[0]=1;
		for(int i=1;i<=k;i++) {
			for(int j=n;j>=i;j--) {
				dp[j]+=dp[j-i];
				dp[j]%=mod;
			}
		}
		for(int i=0;i<=n;i++) {
			if(s-i<=m) {
				ret+=dp[i];
				ret%=mod;
			}
		}
		out.println(ret);
	}
}

class FastReader
{
	BufferedReader br;
	StringTokenizer st;

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

	public String next()
	{
		while(st==null || !st.hasMoreElements())//回车，空行情况
		{
			try {
				st = new StringTokenizer(br.readLine());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return st.nextToken();
	}

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

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

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class D {

	static class Scanner{
		BufferedReader br=null;
		StringTokenizer tk=null;
		public Scanner(){
			br=new BufferedReader(new InputStreamReader(System.in));
		}
		public String next() throws IOException{
			while(tk==null || !tk.hasMoreTokens())
				tk=new StringTokenizer(br.readLine());
			return tk.nextToken();
		}
		public int nextInt() throws NumberFormatException, IOException{
			return Integer.valueOf(next());
		}
		public long nextLong() throws NumberFormatException, IOException{
			return Long.valueOf(next());
		}
		public double nextDouble() throws NumberFormatException, IOException{
			return Double.valueOf(next());
		}
	}

	static int R, G;
	static int mod = 1000000007;
	static int[][] dp;

	static int gastado(int level){
		int ret = level * (level + 1);
		return ret/2;
	}

	static int getlevel(){
		int maxlevel = 0;
		while(gastado(maxlevel) <= R + G)
			maxlevel++;
		return maxlevel - 1;
	}

	public static void main(String args[]) throws NumberFormatException, IOException{
		Scanner sc = new Scanner();
		R = sc.nextInt();
		G = sc.nextInt();
		dp = new int[2][R + 1];
		int h = getlevel();
		for(int i = 0; i <= R; i++)
			dp[h & 1][i] = 1;
		for(int i = h - 1; i >= 0; i--){
			for(int r = 0; r <= Math.min(R, gastado(i)); r++){
				int quedarojo = R - r;
				int quedaverde = G - (gastado(i) - r);
				if (quedaverde < 0)
					continue;
				int current = i + 1;
				dp[i & 1][r] = 0;
				if (quedarojo >= current)
					dp[i & 1][r] = dp[(i + 1)&1][r + current];
				if (quedaverde >= current){
					dp[i & 1][r] = dp[i & 1][r] +  dp[(i + 1)&1][r];
					if (dp[i & 1][r] >= mod) dp[i & 1][r] -= mod;
				}
			}
		}
		System.out.println(dp[0][0]);
	}
}

import java.util.Arrays;
import java.util.Scanner;

/**
 *
 */

/**
 * @author �
 *
 */
public final class b4 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Scanner datain = new Scanner(System.in);
        long r = datain.nextLong();
        long g = datain.nextLong();
        double nf = (-1+Math.sqrt(8*r+8*g+1))/2;
        int n;
        n = (int)nf;
        long[] dp = new long[400000];// pts red
        long[] dp2 = new long[400000];
        Arrays.fill(dp, 0);
        Arrays.fill(dp2, 0);
        dp[0] = 1;
        for(int l=1;l<=n;l++){
            int nl = l*(l+1)/2;
            for(int j=0;j<=nl;j++){
                if((dp[j]>0)&&(j+l<=r)){dp2[j+l]+=dp[j];};
                if((dp[j]>0)&&(nl-j<=g)){dp2[j]+=dp[j];};
                dp2[j]%=1000000007;
            }
            for(int j=0;j<=nl;j++){
                dp[j]=dp2[j];
                dp2[j]=0;
            }
        }
        for(int j=1;j<=n*(n+1)/2;j++)
        {dp[0]+=dp[j];
        dp[0]%=1000000007;}
        System.out.print(dp[0]);
    }

}

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;
import java.util.Stack;
import java.util.StringTokenizer;

public class Main {
	static boolean can (int r , int g , int h) {
		while (h > 0 && (r > 0 || g > 0) && (r >= h || g >= h)) {
			if (r < g) {
				if (r >= h)
					r -= h;
				else g -= h;
			}

			else if (g >= h)
				g -= h;
			else r -= h;
			h -- ;
		}
		return h <= 0;
	}
	static int getH (int r , int g) {
		int lo = 0 ;
		int hi = (int)1e5;
		int max = 0;
		for(int i = 0 ; i < 20 ; ++i) {
			int mid = lo + ((hi - lo) >> 1);
			if (can(r , g , mid)) {
				max = Math.max(max, mid);
				lo = mid + 1;
			}
			else hi = mid - 1 ;
		}
		return max;
	}

	public static void main(String[] args) throws Exception {
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(bf.readLine());
			int r = Integer.parseInt(st.nextToken());
			int g = Integer.parseInt(st.nextToken());

			int MOD = (int)1e9 + 7;
			int H = getH (r , g);
			int dp [][] = new int[2][r + 1];

			dp[1][0] = 1;
			int parity = 0;
			for (int curH = 1 ; curH <= H ; ++ curH) {

				int neededBlocksSoFar = ((curH) * (curH + 1)) >> 1;

				dp[parity] = new int [r + 1];
				for (int red = Math.max(0 , Math.min(neededBlocksSoFar - g, curH)) ; red <= r ; ++ red) {

					if (red >= curH)
						dp[parity][red] = (dp[parity][red] + dp[parity ^ 1][red - curH ]);
					if (dp[parity][red] >= MOD) dp[parity][red] -= MOD;
					if (g >= neededBlocksSoFar - red)
						dp[parity][red] = (dp[parity][red] + dp[parity ^ 1][red]) % MOD;
					if (dp[parity][red] >= MOD) dp[parity][red] -= MOD;

				}
				parity ^= 1;
			}

			int cnt = 0 ;
			for (int i = 0 ; i <= r ; ++ i) {
				cnt = (cnt + dp[parity ^ 1][i]);
				if (cnt >= MOD) cnt -= MOD;
			}

			PrintWriter out = new PrintWriter(System.out);
			out.print((cnt % MOD)); out.flush(); out.close();
	}

}

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

public class C {
	static int mod = (int)1e9+7;
	public static void main(String[] args) throws NumberFormatException, IOException {
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);
		int r = sc.nextInt(), g = sc.nextInt();
		int h = 1, sum = 1;
		while(sum <= r+g){
			sum += ++h;
		}
		int [][] dp = new int[2][r+1];
		Arrays.fill(dp[h%2], 1);
		int tot = h * (h-1) / 2;
		for (int i = h-1, cur = i%2; i > 0; --i, cur ^= 1) {
			tot -= i;
			for (int j = 0; j < dp[cur].length; ++j) {
				dp[cur][j] = 0;
				if(j - i >= 0)
					dp[cur][j] = dp[1^cur][j - i];
				//rem green blocks in level i
				int gg = g - (tot - (r-j));
				if(gg >= i)
					dp[cur][j] += dp[1^cur][j];
				if(dp[cur][j] >= mod)
					dp[cur][j] -= mod;
				}
		}
		out.println(dp[1][r]);
		out.close();
	}

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

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

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

		public int nextInt() throws NumberFormatException, IOException {
			return Integer.parseInt(next());
		}
	}

}

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

public class Main {

	static int n ,  m ;
	static final int mod = 1000000007;
	static int ans ;
	static int[] dp,temp;
	static  int R,G ;
	static int height ;

	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);

		R = sc.nextInt();
		G = sc.nextInt();

		int total = R + G ;
		height = 1 ;

		for(  ; height < 10000 ; ++height)
			if( height *(height +1)  >  2 * total   )
				{
				break ;
				}
		height--;

		int min = Math.min ( R , G );
		int max = Math.max( R ,G );

		R = min ;
		G = max;

		dp = new int[ height*(height+1)/2 + 1 ];

		int r , g ;

		r = height*(height + 1)/2  - G ;

		for( int i =  Math.max(0,r); i <= R && i <= height*(height+1)/2 ; ++i )
			dp[i]= 1;

		while( --height >= 1 )
		{
			temp = new int[ height*(height+1)/2 + 1 ];

			for(r = 0 ; r <= R && r <= height*(height+1)/2 ; ++r )
				temp[r] = (dp[r] + dp[r+height+1] )%mod;

			dp = temp ;

		}

		int ans = dp[0]+dp[1];

		System.out.println( ans%mod ) ;

	}

	//  r remaining , h completely filled

	static class MyScanner {
	      BufferedReader br;
	      StringTokenizer st;

	      public MyScanner() {
	         br = new BufferedReader(new InputStreamReader(System.in),8*1024);
	      }

	      String next() {
	          while (st == null || !st.hasMoreElements()) {
	              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());
	      }

	      String nextLine(){
	          String str = "";
		  try {
		     str = br.readLine();
		  } catch (IOException e) {
		     e.printStackTrace();
		  }
		  return str;
	      }

	   }

static class MyWriter {
	    BufferedWriter bw;

	    public  MyWriter() {
	       bw = new BufferedWriter(new OutputStreamWriter(System.out),8*1024);
	    }

	    void print(String s)
	    {
	    	try {
					bw.write( s , 0 , s.length() );

				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
	    }

	    void println(String s)
	    {
	    	try {
				bw.write( s , 0 , s.length() );
				bw.newLine();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	    }

	 void close()
	 {
		 try {
			bw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	 }
	}

}

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

public class problem478D {

    public static long MOD=1000*1000*1000+7;

    public static void main(String[]args)throws IOException{
        BufferedReader x=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer(x.readLine());
        int r=Integer.parseInt(st.nextToken());
        int g=Integer.parseInt(st.nextToken());
        if (r==0){System.out.println(1);System.exit(0);}
        long[]arr=new long[r+1];
        arr[0]=1;
        arr[1]=1;
        int h=2;
        long ans=0;
        for (h=2; h*(h+1)/2<=r+g; h++){
            for (int i=r; i>=h; i--){
                arr[i]+=arr[i-h];
                if (arr[i]>=MOD)arr[i]-=MOD;
            }
        }
        h--;
        for (int i=Math.max(0,(h+1)*h/2-g); i<=r; i++){
            ans+=arr[i];
        }
        ans%=MOD;
        System.out.println(ans);

    }
}

// Codeforces Round #273 (Div.2) D. Red-Green Towers (478/D)

import java.util.Scanner;

public class RedGreenTowers {

	private static final int MOD = 1000000007;

	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);

		int R = scan.nextInt();
		int G = scan.nextInt();

		int[][] dp = new int[2][R + 1];
		int curr = 0;
		int res = 0;
		dp[1][0] = 1;
		for (int h = 1, sum = 1; sum <= R + G; sum += ++h) {
			int prev = 1 - curr;
			res = 0;
			for (int r = Math.max(0, sum - G); r <= R; ++r) {
				dp[curr][r] = dp[prev][r];
				if (r - h >= 0) {
					dp[curr][r] = (dp[curr][r] + dp[prev][r - h]) % MOD;
				}
				res = (res + dp[curr][r]) % MOD;
			}
			curr = prev;
		}
		System.out.println(res);
	}
}

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

import static java.lang.Math.*;

public class Solution implements Runnable {

    final int MOD = (int)(1e9) + 7;

    void solve() throws Exception {
        int r = sc.nextInt();
        int g = sc.nextInt();
        int lf = 0, rg = 700;
        rg = 0;
        while (rg * (rg + 1) / 2 <= r + g) rg++;
        --rg;
        int dp[][] = new int[2][g + 1];
        dp[0][0] = 1;
        for (int lvl = 0, sm = 0; lvl < rg; lvl++) {
            int X = (lvl & 1);
            int Y = (X ^ 1);
            Arrays.fill(dp[Y], 0);
            int cur = rg - lvl;
            for (int i = 0; i <= min(sm, g); i++) {
                if (dp[X][i] > 0) {
                    if (i + cur <= g) {
                        dp[Y][i + cur] += dp[X][i];
                        if (dp[Y][i + cur] >= MOD)
                            dp[Y][i + cur] -= MOD;
                    }
                    if (sm - i + cur <= r) {
                        dp[Y][i] += dp[X][i];
                        if (dp[Y][i] >= MOD)
                            dp[Y][i] -= MOD;
                    }
                }
            }
            sm += cur;
        }
        int ans = 0;
        for (int i = 0; i <= g; i++) {
            ans = ans + dp[rg & 1][i];
            if (ans >= MOD)
                ans -= MOD;
        }
        out.println(ans);
    }

    BufferedReader in;
    PrintWriter out;
    FastScanner sc;

    static Throwable throwable;

    public void run() {
        try {
            in = new BufferedReader(new InputStreamReader(System.in));
            out = new PrintWriter(System.out);
            //in = new BufferedReader(new FileReader(".in"));
            //out = new PrintWriter(".out");
            sc = new FastScanner(in);
            solve();
        } catch (Exception e) {
            throwable = e;
        } finally {
            out.close();
        }
    }

    public static void main(String[] args) throws Throwable {
        Thread thread = new Thread(null, new Solution(), "", (1 << 26));
        thread.start();
        thread.join();
        thread.run();
        if (Solution.throwable != null)
            throw Solution.throwable;
    }

}

class FastScanner {
    BufferedReader reader;
    StringTokenizer strTok;

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

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

    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());
    }
}

// TO LOVE IS TO KNOW WHAT'S YOUR WORTH. //
// Author :- Saurabh//
//BIT MESRA, RANCHI//
import java.io.*;
import java.util.*;
import static java.lang.Math.*;
public class redGreeTowers {

    static void Bolo_Jai_Mata_Di() {

        int r=ni(),g=ni();
        tsc();

        int maxh=1;
        for(;((maxh+1)*(maxh+2))/2<=(r+g);maxh++);
        int rem=(r+g)-(maxh*(maxh+1)/2);
        long dp[]=new long[200020];
        for(int i=0;i<=rem;i++)dp[i]=1;
        for(int i=1;i<=maxh;i++){
            for(int j=r-i;j>=0;j--){
                dp[i+j]=mod(dp[i+j]+dp[j]);
            }
        }
        pl(dp[r]);

        flush();
    }

    static long mod(long x) {
        return x > mod9 ? x-mod9 : x;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //THE DON'T CARE ZONE BEGINS HERE...//

    static Calendar ts, te;                                                  //For time calculation
    static int mod9 = 1000000007;
    static int n, m, k, t, mod = 998244353;
    static Lelo input = new Lelo(System.in);
    static PrintWriter pw = new PrintWriter(System.out, true);

    public static void main(String[] args) {      //threading has been used to increase the stack size.

        new Thread(null, null, "BlackRise", 1 << 25)  //the last parameter is stack size desired.,
        {
            public void run() {

                try {

                    Bolo_Jai_Mata_Di();
                } catch (Exception e) {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }.start();
    }

    static class Lelo {                                              //Lelo class for fast input
        private InputStream ayega;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private SpaceCharFilter filter;

        public Lelo(InputStream ayega) {
            this.ayega = ayega;
        }

        public int read() {
            if (numChars == -1)
                throw new InputMismatchException();

            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = ayega.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }

                if (numChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public String nextLine() {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        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;
        }

        public long nextLong() {
            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 double nextDouble() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            double res = 0;
            while (!isSpaceChar(c) && c != '.') {
                if (c == 'e' || c == 'E')
                    return res * Math.pow(10, nextInt());
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            if (c == '.') {
                c = read();
                double m = 1;
                while (!isSpaceChar(c)) {
                    if (c == 'e' || c == 'E')
                        return res * Math.pow(10, nextInt());
                    if (c < '0' || c > '9')
                        throw new InputMismatchException();
                    m /= 10;
                    res += (c - '0') * m;
                    c = read();
                }
            }
            return res * sgn;
        }

        public String readString() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = read();
            }
            while (!isSpaceChar(c));

            return res.toString();
        }

        public boolean isSpaceChar(int c) {
            if (filter != null)
                return filter.isSpaceChar(c);
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public String next() {
            return readString();
        }

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

    // functions to take input//
    static int ni() {
        return input.nextInt();
    }

    static long nl() {
        return input.nextLong();
    }

    static double nd() {
        return input.nextDouble();
    }

    static String ns() {
        return input.readString();
    }

    //functions to give output
    static void pl() {
        pw.println();
    }

    static void p(Object o) {
        pw.print(o + " ");
    }

    static void pws(Object o) {
        pw.print(o + "");
    }

    static void pl(Object o) {
        pw.println(o);
    }

    static void tsc()                                          //calculates the starting time of execution
    {
        ts = Calendar.getInstance();
        ts.setTime(new Date());
    }

    static void tec()                                          //calculates the ending time of execution
    {
        te = Calendar.getInstance();
        te.setTime(new Date());
    }

    static void pwt()                                          //prints the time taken for execution
    {
        pw.printf("\nExecution time was :- %f s\n", (te.getTimeInMillis() - ts.getTimeInMillis()) / 1000.00);
    }

    static void sort(int ar[], int n) {
        for (int i = 0; i < n; i++) {
            int ran = (int) (Math.random() * n);
            int temp = ar[i];
            ar[i] = ar[ran];
            ar[ran] = temp;
        }
        Arrays.sort(ar);
    }

    static void sort(long ar[], int n) {
        for (int i = 0; i < n; i++) {
            int ran = (int) (Math.random() * n);
            long temp = ar[i];
            ar[i] = ar[ran];
            ar[ran] = temp;
        }
        Arrays.sort(ar);
    }

    static void sort(char ar[], int n) {
        for (int i = 0; i < n; i++) {
            int ran = (int) (Math.random() * n);
            char temp = ar[i];
            ar[i] = ar[ran];
            ar[ran] = temp;
        }
        Arrays.sort(ar);
    }

    static void flush() {
        tec();                  //ending time of execution
        //pwt();                //prints the time taken to execute the program
        pw.flush();
        pw.close();
    }
}

import java.io.*;
import java.util.Locale;
import java.util.StringTokenizer;

public class A implements Runnable {

    private static final boolean ONLINE_JUDGE = System.getProperty("ONLINE_JUDGE") != null;

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

    private void init() throws FileNotFoundException {
        Locale.setDefault(Locale.US);
        String fileName = "";
        if (ONLINE_JUDGE && fileName.isEmpty()) {
            in = new BufferedReader(new InputStreamReader(System.in));
            out = new PrintWriter(System.out);
        } else {
            if (fileName.isEmpty()) {
                in = new BufferedReader(new FileReader("input.txt"));
                out = new PrintWriter("output.txt");
            } else {
                in = new BufferedReader(new FileReader(fileName + ".in"));
                out = new PrintWriter(fileName + ".out");
            }
        }
    }

    String readString() {
        while (!tok.hasMoreTokens()) {
            try {
                tok = new StringTokenizer(in.readLine());
            } catch (Exception e) {
                return null;
            }
        }
        return tok.nextToken();
    }

    int readInt() {
        return Integer.parseInt(readString());
    }

    long readLong() {
        return Long.parseLong(readString());
    }

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

    int[] readIntArray(int size) {
        int[] a = new int[size];
        for (int i = 0; i < size; i++) {
            a[i] = readInt();
        }
        return a;
    }

    public static void main(String[] args) {
        //new Thread(null, new _Solution(), "", 128 * (1L << 20)).start();
        new A().run();
    }

    long timeBegin, timeEnd;

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

    @Override
    public void run() {
        try {
            timeBegin = System.currentTimeMillis();
            init();
            solve();
            out.close();
            time();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }
    }

    private int aiverson(boolean good) {
        return good ? 1 : 0;
    }

    private void solve() {
        int g = readInt();
        int r = readInt();
        int maxH = 1;
        int left = 1, right = r + g;
        while (left <= right) {
            int mid = (left + right) >> 1;
            if (1l * mid * (mid + 1) / 2 <= r + g) {
                maxH = mid;
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }

        int[][] dp = new int[2][r + 1];
        dp[0][0] = 1;
        for (int level = 1; level <= maxH; level++) {
            int cur = level % 2;
            for (int spentRed = 0; spentRed <= r; spentRed++) {
                dp[cur][spentRed] = 0;
                if (spentRed - level >= 0) {
                    dp[cur][spentRed] += dp[1 - cur][spentRed - level];
                }
                int spentGreen = level * (level + 1) / 2 - spentRed;
                if (spentGreen >= 0 && spentGreen <= g && spentGreen - level >= 0) {
                    dp[cur][spentRed] += dp[1 - cur][spentRed];
                }
                dp[cur][spentRed] %= mod;
            }
        }

        int answer = 0;
        for (int count : dp[maxH % 2]) {
            answer = (answer + count) % mod;
        }

        out.println(answer);
    }

    final int mod = 1000 * 1000 * 1000 + 7;
}

import java.io.InputStreamReader;
import java.io.IOException;
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
 */
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);
		TaskD solver = new TaskD();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskD {
    private static final int MODULO = (int) 1e9 + 7;

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int red = in.nextInt();
        int green = in.nextInt();
        if (red > green) {
            int tmp = red;
            red = green;
            green = tmp;
        }
        int maxHeight = 1;
        int sum = 0;
        int[] ways = new int[red + 1];
        ways[0] = 1;
        while (maxHeight * (maxHeight + 1) / 2 <= red + green) {
            sum = Math.min(red, sum + maxHeight);
            for (int i = sum; i >= maxHeight; --i) {
                int w = ways[i] + ways[i - maxHeight];
                if (w >= MODULO) w -= MODULO;
                ways[i] = w;
            }
            ++maxHeight;
        }
        --maxHeight;
        int answer = 0;
        for (int takenRed = 0; takenRed <= maxHeight * (maxHeight + 1) / 2 && takenRed <= red; ++takenRed)
            if (maxHeight * (maxHeight + 1) / 2 - takenRed <= green) {
                answer += ways[takenRed];
                if (answer >= MODULO) answer -= MODULO;
            }
        out.println(answer);
    }
}

class InputReader {
    private BufferedReader reader;
    private StringTokenizer tokenizer;

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

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

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

}

import java.util.Scanner;
import java.io.PrintWriter;

public class d {
	private static final int maxh = 1000;
	private static final long mod = 1000000000 + 7;
	private static int sumx(int k){
		int l = 0;
		int r = maxh;
		while (r - l > 1){
			int m = (r + l) >> 1;
			if (m * (m + 1) > 2 * k)
				r = m;
			else if (m * (m + 1) < 2 * k)
				l = m;
			else
				return m;
		}
		return l;
	}
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		PrintWriter out = new PrintWriter(System.out);
		int r = 0, g = 0;
		r = in.nextInt();
		g = in.nextInt();
		if (r < g){
			int t = r;
			r = g;
			g = t;
		}
		int h = sumx(r + g);
		int dp[][] = new int[2][r + 1];
		for (int i = 0; i < r + 1; i++)
			dp[0][i] = 0;
		dp[0][0] = dp[0][1] = 1;
		int cur = 1;
		for (int i = 1; i < h; i++){
			for (int j = 0; j <= i; j++)
				dp[cur][j] = dp[cur ^ 1][j];
			for (int j = i + 1; j <= r; j++){
				dp[cur][j] = dp[cur ^ 1][j - i - 1] + dp[cur ^ 1][j];
				if (dp[cur][j] >= mod)
					dp[cur][j] -= mod;
			}
			cur = cur ^ 1;
		}
		long ans = 0;
		for (int i = Math.max(0, h * (h + 1) / 2 - g); i <= r; i++){
			ans += (long)dp[cur ^ 1][i];
		}
		ans %= mod;
		out.println(ans);
		in.close();
		out.close();
	}
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

/**
 * Created by ahmadi on 6/29/18.
 */
public class Main {
    public static int maxTriangular(int i){
        return (int)(Math.floor((1 + Math.sqrt(8*(i)+1))/2)-1);
    }
    public static int dp(int r, int g, int h){
        if (h == 0)
            return 1;
        int rs = 0;
        int gs = 0;
        if (h <= r)
            rs = dp(r-h,g, h-1);
        if (h <= g)
            gs = dp(r,g-h, h-1);
        return rs + gs;
    }
    public static void main(String[] args) {
        BufferedReader br = new BufferedReader(
                new InputStreamReader(System.in));
        TreeSet<Integer> set = new TreeSet<Integer>();
        StringTokenizer st;
        try {
            st = new StringTokenizer(br.readLine());
            int r = Integer.parseInt(st.nextToken());
            int g = Integer.parseInt(st.nextToken());
            int h = maxTriangular(r+g);
            int[] dp = new int[r+1];
            int re = (h + 1) * h / 2 - g;
            int ans = 0;
            dp[0] = 1;
            for(int i = 1; i <= h; i++){
                for(int j = r; j >= 0; j--){
                    if(j >= i)
                        dp[j] = (dp[j] + dp[j-i]) % 1000000007;
                    if(i == h && j >= re)
                        ans = (ans + dp[j]) % 1000000007;
                }
            }
            System.out.println(ans);
        } catch (IOException e) {
        }

    }
}

import java.io.InputStreamReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
import java.util.InputMismatchException;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.StringTokenizer;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author Andrey Rechitsky (arechitsky@gmail.com)
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		FastScanner in = new FastScanner(inputStream);
		FastPrinter out = new FastPrinter(outputStream);
		TaskD solver = new TaskD();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskD {
    static long MOD = 1000000007;
    public void solve(int testNumber, FastScanner in, FastPrinter out) {
        int r = in.nextInt();
        int g = in.nextInt();
        if (r==0 || g==0){
            out.printLine(1);
            return;
        }
        int h = 0;
        while (h*(h+1)/2<=r+g) h++;
        h--;

        int []d = new int[2];
        d[0] = 1;
        d[1] = 1;
        for (int i = 1; i < h; i++) {
            int []d2 = new int[(i+2)*(i+1)/2+1];
            for (int j = 0; j < d2.length; j++) {
                d2[j] = 0;
                if (j>= i+1) d2[j] += d[j-i-1];
                if (j<d.length) d2[j] += d[j];
                d2[j] %= MOD;
            }
            d = d2;
        }
        int usecount = h*(h+1)/2;
        int ans = 0;
        for (int i = Math.max(0, r-usecount); i < Math.min(r, r + g - usecount)+1; i++) {
            ans+=d[r-i];
            ans %= MOD;
        }
        out.printLine(ans);
    }
}

class FastScanner {

    private BufferedReader reader;
    private StringTokenizer st;

    public FastScanner(InputStream stream) {
        this.reader = new BufferedReader(new InputStreamReader(stream));
        this.st = new StringTokenizer("");
    }

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

    public String next(){
        while (!st.hasMoreTokens()){
            st = new StringTokenizer(readLine());
        }
        return st.nextToken();
    }

    private String readLine() {
        try {
            String line = reader.readLine();
            if (line==null) throw new InputMismatchException();
            return line;
        } catch (IOException e) {
            throw new InputMismatchException();
        }
    }

}

class FastPrinter {
    private final PrintWriter writer;

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

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

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

}

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

import static java.lang.Math.*;
import static java.util.Arrays.*;

public class cf478d {

    public static void main(String[] args) throws IOException {
        int r = rni(), g = ni(), h = floori((sqrt(8 * (r + g) + 1) - 1) / 2), n = h * (h + 1) / 2;
        long[] dp = new long[r + 1];
        dp[0] = 1;
        // prln(h);
        for(int i = 1; i <= h; ++i) {
            for(int j = r; j >= i; --j) {
                dp[j] = (dp[j] + dp[j - i]) % IBIG;
            }
        }
        long ans = 0;
        int lim = min(r, n);
        for(int i = max(0, n - g); i <= lim; ++i) {
            ans = (ans + dp[i]) % IBIG;
        }
        prln(ans);
        close();
    }

    static BufferedReader __in = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter __out = new PrintWriter(new OutputStreamWriter(System.out));
    static StringTokenizer input;
    static Random rand = new Random();

    // references
    // IBIG = 1e9 + 7
    // IRAND ~= 3e8
    // IMAX ~= 2e10
    // LMAX ~= 9e18
    // constants
    static final int IBIG = 1000000007;
    static final int IRAND = 327859546;
    static final int IMAX = 2147483647;
    static final int IMIN = -2147483648;
    static final long LMAX = 9223372036854775807L;
    static final long LMIN = -9223372036854775808L;
    // util
    static int minof(int a, int b, int c) {return min(a, min(b, c));}
    static int minof(int... x) {return x.length == 1 ? x[0] : x.length == 2 ? min(x[0], x[1]) : min(x[0], minstarting(1, x));}
    static int minstarting(int offset, int... x) {assert x.length > 2; return offset == x.length - 2 ? min(x[offset], x[offset + 1]) : min(x[offset], minstarting(offset + 1, x));}
    static long minof(long a, long b, long c) {return min(a, min(b, c));}
    static long minof(long... x) {return x.length == 1 ? x[0] : x.length == 2 ? min(x[0], x[1]) : min(x[0], minstarting(1, x));}
    static long minstarting(int offset, long... x) {assert x.length > 2; return offset == x.length - 2 ? min(x[offset], x[offset + 1]) : min(x[offset], minstarting(offset + 1, x));}
    static int maxof(int a, int b, int c) {return max(a, max(b, c));}
    static int maxof(int... x) {return x.length == 1 ? x[0] : x.length == 2 ? max(x[0], x[1]) : max(x[0], maxstarting(1, x));}
    static int maxstarting(int offset, int... x) {assert x.length > 2; return offset == x.length - 2 ? max(x[offset], x[offset + 1]) : max(x[offset], maxstarting(offset + 1, x));}
    static long maxof(long a, long b, long c) {return max(a, max(b, c));}
    static long maxof(long... x) {return x.length == 1 ? x[0] : x.length == 2 ? max(x[0], x[1]) : max(x[0], maxstarting(1, x));}
    static long maxstarting(int offset, long... x) {assert x.length > 2; return offset == x.length - 2 ? max(x[offset], x[offset + 1]) : max(x[offset], maxstarting(offset + 1, x));}
    static int powi(int a, int b) {if(a == 0) return 0; int ans = 1; while(b > 0) {if((b & 1) > 0) ans *= a; a *= a; b >>= 1;} return ans;}
    static long powl(long a, int b) {if(a == 0) return 0; long ans = 1; while(b > 0) {if((b & 1) > 0) ans *= a; a *= a; b >>= 1;} return ans;}
    static int floori(double d) {return (int)d;}
    static int ceili(double d) {return (int)ceil(d);}
    static long floorl(double d) {return (long)d;}
    static long ceill(double d) {return (long)ceil(d);}
    static void shuffle(int[] a) {int n = a.length - 1; for(int i = 0; i < n; ++i) {int ind = randInt(i, n); int swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void shuffle(long[] a) {int n = a.length - 1; for(int i = 0; i < n; ++i) {int ind = randInt(i, n); long swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void shuffle(double[] a) {int n = a.length - 1; for(int i = 0; i < n; ++i) {int ind = randInt(i, n); double swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static <T> void shuffle(T[] a) {int n = a.length - 1; for(int i = 0; i < n; ++i) {int ind = randInt(i, n); T swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void sort(int[] a) {shuffle(a); Arrays.sort(a);}
    static void sort(long[] a) {shuffle(a); Arrays.sort(a);}
    static void sort(double[] a) {shuffle(a); Arrays.sort(a);}
    static void qsort(int[] a) {Arrays.sort(a);}
    static void qsort(long[] a) {Arrays.sort(a);}
    static void qsort(double[] a) {Arrays.sort(a);}
    static int randInt(int min, int max) {return rand.nextInt(max - min + 1) + min;}
    // input
    static void r() throws IOException {input = new StringTokenizer(__in.readLine());}
    static int ri() throws IOException {return Integer.parseInt(__in.readLine());}
    static long rl() throws IOException {return Long.parseLong(__in.readLine());}
    static int[] ria(int n) throws IOException {int[] a = new int[n]; input = new StringTokenizer(__in.readLine()); for(int i = 0; i < n; ++i) a[i] = Integer.parseInt(input.nextToken()); return a;}
    static long[] rla(int n) throws IOException {long[] a = new long[n]; input = new StringTokenizer(__in.readLine()); for(int i = 0; i < n; ++i) a[i] = Long.parseLong(input.nextToken()); return a;}
    static char[] rcha() throws IOException {return __in.readLine().toCharArray();}
    static String rline() throws IOException {return __in.readLine();}
    static int rni() throws IOException {input = new StringTokenizer(__in.readLine()); return Integer.parseInt(input.nextToken());}
    static int ni() {return Integer.parseInt(input.nextToken());}
    static long rnl() throws IOException {input = new StringTokenizer(__in.readLine()); return Long.parseLong(input.nextToken());}
    static long nl() {return Long.parseLong(input.nextToken());}
    // output
    static void pr(int i) {__out.print(i);}
    static void prln(int i) {__out.println(i);}
    static void pr(long l) {__out.print(l);}
    static void prln(long l) {__out.println(l);}
    static void pr(double d) {__out.print(d);}
    static void prln(double d) {__out.println(d);}
    static void pr(char c) {__out.print(c);}
    static void prln(char c) {__out.println(c);}
    static void pr(char[] s) {__out.print(new String(s));}
    static void prln(char[] s) {__out.println(new String(s));}
    static void pr(String s) {__out.print(s);}
    static void prln(String s) {__out.println(s);}
    static void pr(Object o) {__out.print(o);}
    static void prln(Object o) {__out.println(o);}
    static void prln() {__out.println();}
    static void pryes() {__out.println("yes");}
    static void pry() {__out.println("Yes");}
    static void prY() {__out.println("YES");}
    static void prno() {__out.println("no");}
    static void prn() {__out.println("No");}
    static void prN() {__out.println("NO");}
    static void pryesno(boolean b) {__out.println(b ? "yes" : "no");};
    static void pryn(boolean b) {__out.println(b ? "Yes" : "No");}
    static void prYN(boolean b) {__out.println(b ? "YES" : "NO");}
    static void prln(int... a) {for(int i = 0, len = a.length - 1; i < len; __out.print(a[i]), __out.print(' '), ++i); __out.println(a[a.length - 1]);}
    static void prln(long... a) {for(int i = 0, len = a.length - 1; i < len; __out.print(a[i]), __out.print(' '), ++i); __out.println(a[a.length - 1]);}
    static <T> void prln(Collection<T> c) {int n = c.size() - 1; Iterator<T> iter = c.iterator(); for(int i = 0; i < n; __out.print(iter.next()), __out.print(' '), ++i); if(n >= 0) __out.println(iter.next());}
    static void h() {__out.println("hlfd");}
    static void flush() {__out.flush();}
    static void close() {__out.close();}
}

import java.awt.Point;
import java.io.*;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.security.KeyStore.Entry;
import java.util.*;
import java.io.*;
public class Tests {
	static Scanner in = new Scanner();
	static PrintWriter out = new PrintWriter (System.out);
	static int Max = (2*100000)+10;
	static int Mod = 1000000000 + 7;
    public static void main (String[] test) throws NumberFormatException, IOException{
    	int r = in.nextInt();
    	int g = in.nextInt();
    	int h;
    	for( h = 1 ; (h*(h+1))/2<= r+g ; h++);
    	h = h-1;
    	//out.println(h);
    	//base case
    	/*
    	 * (r+g) - h*(h+1)/2
    	 *
    	 */
    	int dp [] = new int [Max];
    	int base = (r+g) - (h*(h+1))/2;
    	for(int i = 0 ; i<= base ; i++){
    		dp[i] = 1;
    	}
    	/*
    	for(int level = 1 ; level<= h ; level++){
    		for(int red = r - level ; red >= 0 ; red-- ){
    			dp[level + red] = (dp[level + red] + dp[red]) %	Mod;
    		}
    	}
    	out.println(dp[r]%Mod);
    	*/
    	for(int level = 1 ; level<= h ; level++){
    		for(int green = g - level ; green >= 0 ; green-- ){
    			dp[level + green] = (dp[level + green] + dp[green]) %	Mod;
    		}
    	}
    	out.printf("%d\n",dp[g]%Mod);
        out.flush();
    	out.close();
    }
	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

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

		Scanner(String file) throws FileNotFoundException {
			br = new BufferedReader(new FileReader(file));
		}

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

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

		String nextLine() throws IOException {
			return br.readLine();
		}

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

	}

}

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.Arrays;
import java.util.StringTokenizer;

public class D {

    static StringTokenizer st;
    static BufferedReader br;
    static PrintWriter pw;
    public static void main(String[] args) throws IOException {
        br = new BufferedReader(new InputStreamReader(System.in));
        pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
        int r = nextInt();
        int g = nextInt();
        if (r > g) {
            int t = r;
            r = g;
            g = t;
        }
        int h = 0;
        for (int H = 1; ; H++) {
            if (H*(H+1) / 2 <= r+g)
                h = H;
            else
                break;
        }
        int mod = (int) (1e9+7);
        long ans = 0;
        int max = (int) 2e5;
        int[]dp1 = new int[max+1], dp2 = new int[max+1];
        dp1[0] = 1;
        for (int i = 1; i <= h; i++) {
            for (int j = 0; j <= max; j++) {
                dp2[j] = dp1[j];
                if (j-i >= 0) {
                    dp2[j] += dp1[j-i];
                    if (dp2[j] >= mod)
                        dp2[j] -= mod;
                }
            }
            for (int j = 0; j <= max; j++) {
                dp1[j] = dp2[j];
            }
        }
        int all = h * (h+1) / 2;
        for (int i = 0; i <= r; i++) {
            if (g >= all-i) {
                ans += dp1[i];
                if (ans >= mod)
                    ans -= mod;
            }
        }
        System.out.println(ans);
        pw.close();
    }
    private static int nextInt() throws IOException {
        return Integer.parseInt(next());
    }
    private static long nextLong() throws IOException {
        return Long.parseLong(next());
    }
    private static double nextDouble() throws IOException {
        return Double.parseDouble(next());
    }
    private static String next() throws IOException {
        while (st==null || !st.hasMoreTokens())
            st = new StringTokenizer(br.readLine());
        return st.nextToken();
    }
}

import java.awt.Point;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Currency;
import java.util.HashSet;
import java.util.List;
import java.util.SortedSet;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.TreeSet;

/**
 * @author Jens Staahl
 */

public class Prac {

	// some local config
	// static boolean test = false ;
	private boolean test = System.getProperty("ONLINE_JUDGE") == null;
	static String testDataFile = "testdata.txt";
	// static String testDataFile = "testdata.txt";
	private static String ENDL = "\n";
	// Just solves the acutal kattis-problem
	ZKattio io;
	private void solve() throws Throwable {
		io = new ZKattio(stream);
		int g = io.getInt(), r = io.getInt();
		int h = 0;
		int sum = g + r;

		while(sum > 0) {
			h ++;
			sum -= h;
		}
		if(sum < 0 ) {
			h --;
		}
		long[] dp = new long[r+1];
		dp[0] = 1;
		final int mod = 1000000007;
		for (int layer = 1; layer <= h ; layer++) {
			for (int used = r; used >= 0; used--) {
				if(r - used > 0 && used + layer <= r) {
					dp[used+layer] += dp[used];
					if(dp[used + layer] > mod) {
						dp[used+ layer] -= mod;
					}
				}
			}
		}
		long ans = 0;
		int cnt = h * (h+1)/2;
		for (int i = 0; i < dp.length; i++) {
			if(i + g >= cnt) {
				ans += dp[i];
				if(ans > mod) {
					ans -= mod;
				}
			}
		}

		System.out.println(ans % mod);

	}

	public static void main(String[] args) throws Throwable {
		new Prac().solve();

	}

	public Prac() throws Throwable {
		if (test) {
			stream = new FileInputStream(testDataFile);
		}
	}

	InputStream stream = System.in;
	PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));// outStream

	public class ZKattio extends PrintWriter {
		public ZKattio(InputStream i) {
			super(new BufferedOutputStream(System.out));
			r = new BufferedReader(new InputStreamReader(i));
		}

		public ZKattio(InputStream i, OutputStream o) {
			super(new BufferedOutputStream(o));
			r = new BufferedReader(new InputStreamReader(i));
		}

		public boolean hasMoreTokens() {
			return peekToken() != null;
		}

		public int getInt() {
			return Integer.parseInt(nextToken());
		}

		public double getDouble() {
			return Double.parseDouble(nextToken());
		}

		public long getLong() {
			return Long.parseLong(nextToken());
		}

		public String getWord() {
			return nextToken();
		}

		private BufferedReader r;
		private String line;
		private StringTokenizer st;
		private String token;

		private String peekToken() {
			if (token == null)
				try {
					while (st == null || !st.hasMoreTokens()) {
						line = r.readLine();
						if (line == null)
							return null;
						st = new StringTokenizer(line);
					}
					token = st.nextToken();
				} catch (IOException e) {
				}
			return token;
		}

		private String nextToken() {
			String ans = peekToken();
			token = null;
			return ans;
		}
	}
	// System.out;

}

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;
import java.lang.Long;

public class Test {
	static long mod = 1000000007;

	static int contains;

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

		int n = in.nextInt();
		int m = in.nextInt();
		int max = 0;
		for (max = 1; max * (max + 1) / 2 <= n + m; max++)
			;
		max--;
		//System.out.println(max);
		long[] dp = new long[Math.min(n, m) + 1];

		dp[0] = 1;

		for (int i = 1; i <= max; i++) {

			for (int j = dp.length - 1; j >= 0; j--) {
				if (dp[j] > 0 && j + i < dp.length) {
					dp[j + i] += dp[j];
					dp[j] %= mod;

				}
			}

		}
		long result = 0;
		for (int i = Math.max(0,max*(max + 1)/2 - Math.max(n, m)); i <= Math.min(n, m); i++) {
			//System.out.println(i);
			result += dp[i];
			result %= mod;
		}
		out.println(result);
		out.close();
	}

	static int crossProduct(Point a, Point b) {
		return a.x * b.y + a.y * b.x;
	}

	static long squareDist(Point a) {
		long x = a.x;
		long y = a.y;
		return x * x + y * y;
	}

	static Point minus(Point a, Point b) {
		return new Point(a.x - b.x, a.y - b.y);
	}

	public static boolean nextPer(int[] data) {
		int i = data.length - 1;
		while (i > 0 && data[i] < data[i - 1]) {
			i--;
		}
		if (i == 0) {
			return false;
		}
		int j = data.length - 1;
		while (data[j] < data[i - 1]) {
			j--;
		}
		int temp = data[i - 1];
		data[i - 1] = data[j];
		data[j] = temp;
		Arrays.sort(data, i, data.length);
		return true;
	}

	static class Point {
		int x, y;

		public Point(int x, int y) {
			super();
			this.x = x;
			this.y = y;
		}

		public String toString() {
			return "{" + x + " " + y + "}";
		}

	}

	static class Entry implements Comparable<Entry> {
		int x, cost;

		public Entry(int x, int cost) {
			super();
			this.x = x;
			this.cost = cost;
		}

		public int compareTo(Entry o) {
			// TODO Auto-generated method stub
			if (cost > o.cost) {
				return 1;
			} else if (cost == o.cost) {
				return -1;
			}

			return 0;
		}
	}

	static int gcd(int a, int b) {
		if (b == 0) {
			return a;
		}
		return gcd(b, a % b);
	}

	static class Scanner {

		BufferedReader br;
		StringTokenizer st;

		public Scanner() throws FileNotFoundException {
			// System.setOut(new PrintStream(new
			// BufferedOutputStream(System.out), true));
			br = new BufferedReader(new InputStreamReader(System.in));
			// br = new BufferedReader(new InputStreamReader(new
			// FileInputStream(new File("B-large.in"))));
		}

		public String next() {

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

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

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

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

		public String nextLine() {
			st = null;
			try {
				return br.readLine();
			} catch (Exception e) {
				throw new RuntimeException();
			}
		}

		public boolean endLine() {
			try {
				String next = br.readLine();
				while (next != null && next.trim().isEmpty()) {
					next = br.readLine();
				}
				if (next == null) {
					return true;
				}
				st = new StringTokenizer(next);
				return st.hasMoreTokens();
			} catch (Exception e) {
				throw new RuntimeException();
			}
		}
	}
}

import java.util.Scanner;

public class P478D
{
	static int mod = (int)(1e9) + 7;
	public static void main(String[] args)
	{
		Scanner scan = new Scanner(System.in);
		int r = scan.nextInt(), g = scan.nextInt();
		int total = r+g;
		int rows = 0, sum = 0;
		int[] cumul = new int[1000];
		while (true)
		{
			if (sum+rows+1 > total)
				break;
			rows++;
			sum += rows;
			cumul[rows] = sum;
		}
		int[][] dp = new int[2][r+1]; //reds remaining
		dp[0][r] = 1;
		int m = 1;
		for (int i = 1; i <= rows; i++)
		{
			int c = cumul[i-1];
			for (int j = 0; j <= r; j++)
			{
				int greens = g - (c-(r-j));
				int ans = 0;
				if (greens >= i)
					ans += dp[1-m][j];
				if (j+i <= r)
					ans += dp[1-m][j+i];
				dp[m][j] = ans % mod;
			}
			m = 1 - m;
		}
		m = 1-m;
		long ans = 0;
		for (int i = 0; i <= r; i++)
			ans += dp[rows&1][i];
		System.out.println(ans % mod);
	}
}

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;

public class temp4 {
	static class FastReader
    {
        BufferedReader br;
        StringTokenizer st;

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

        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                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());
        }

        String nextLine()
        {
            String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
        }
    }
	static class Print
	{
	    private final BufferedWriter bw;
	    public Print()
	    {
	        bw=new BufferedWriter(new OutputStreamWriter(System.out));
	    }
	    public void print(String str)throws IOException
	    {
	        bw.append(str);
	    }
	    public void println(String str)throws IOException
	    {
	        print(str);
	        bw.append("\n");
	    }
	    public void close()throws IOException
	    {
	        bw.close();
	    }}

		public static void main(String[] args) throws IOException {
			FastReader scn=new FastReader();
			int r=scn.nextInt(),g=scn.nextInt(),h=1,rem=0;
			int[] inf=new int[r+g+1];
			for(h=1;(h*(h+1))/2<=r+g;h++);h--;
			rem=(r+g)-(h*(h+1))/2;
			for(int i=0;i<=rem;i++){
				inf[i]=1;
			}
			for(int i=1;i<=h;i++){
				for(int j=r-i;j>=0;j--){
					inf[j+i]=(inf[j+i]+inf[j])%1000000007;
				}
			}
			System.out.println(inf[r]);

		}
}

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

/**
 * 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;
        Scanner in = new Scanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        DRedGreenTowers solver = new DRedGreenTowers();
        solver.solve(1, in, out);
        out.close();
    }

    static class DRedGreenTowers {
        static int mod = (int) 1e9 + 7;

        public void solve(int testNumber, Scanner sc, PrintWriter pw) {
            int r = sc.nextInt(), g = sc.nextInt(), maxH = bs(r, g);
            int[][] dp = new int[2][r + 1];
            dp[0][r] = 1;
            int cur = 1;
            for (int i = 1; i <= maxH; i++, cur ^= 1) {
                Arrays.fill(dp[cur], 0);
                for (int red = 0; red <= r; red++) {
                    if (dp[cur ^ 1][red] == 0)
                        continue;
                    int green = g - ((i) * (i - 1) / 2) + (r - red);
                    if (red >= i)
                        dp[cur][red - (i)] += dp[cur ^ 1][red] % mod;
                    if (green >= i)
                        dp[cur][red] += dp[cur ^ 1][red] % mod;
                }
            }
            long ans = 0;
            for (int i = 0; i <= r; i++) {
                int green = maxH - (r - i);
            /*if(green>g)
                continue;*/
                ans += dp[cur ^ 1][i];
                ans %= mod;
            }
            pw.println(ans);
        }

        private int bs(int r, int g) {
            int l = 0, h = (int) 1e3, toRet = -1;
            while (l <= h) {
                int mid = (l + h) / 2;
                if ((mid * (mid + 1) / 2) > r + g)
                    h = mid - 1;
                else {
                    l = mid + 1;
                    toRet = mid;
                }
            }
            return toRet;
        }

    }

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;

        public Scanner(FileReader r) {
            br = new BufferedReader(r);
        }

        public Scanner(InputStream s) {
            br = new BufferedReader(new InputStreamReader(s));
        }

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

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

    }
}

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

public class Main
{
    private static final int MOD = 1000000007;

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

        int r = scan.nextInt();
        int g = scan.nextInt();

        int h = 0;
        while(h*(h+1)/2 <= r+g)
            h++;
        h--;

        int MAX = h*(h+1)/2+1;
        int[] dp = new int[MAX];
        dp[0] = 1;
        for(int i = 1;i <= h;i++)
            for(int j = MAX-1;j >= i;j--)
            {
                dp[j] += dp[j-i];
                if(dp[j] >= MOD)
                    dp[j] -= MOD;
            }

        h = h*(h+1)/2;
        int res = 0;
        for(int i = 0;i <= r && i <= h;i++)
            if(g >= h-i)
            {
                res += dp[i];
                if(res >= MOD)
                    res -= MOD;
            }
        System.out.println(res);
    }
}

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

public class Abood2D {

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

		int R = sc.nextInt();
		int G = sc.nextInt();

		int sum = G + R;
		int H = sum == 1? 1 : 0;
		while(sum >= H)
			sum -= H++;
		H--;

		int[] acc = new int[H + 1];

		for (int i = 1; i <= H; i++)
			acc[i] = acc[i - 1] + i;

		int[] last = new int[R + 1];
		Arrays.fill(last, 1);

		for (int i = H - 1; i >= 0; i--) {
			int[] cur = new int[R + 1];

			for (int j = 0; j < cur.length; j++) {
				int r = j;
				int g = G - (acc[i] - (R - r));

				if(g - i >= 1)
					cur[j] += last[j];
				if(r - i >= 1)
					cur[j] += last[j - (i + 1)];

				cur[j] %= (int) 1e9 + 7;
			}
			last = cur;
		}

		out.print(last[R]);

		out.flush();

	}

	static class Scanner

	{
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}

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

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

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

		public String nextLine() throws IOException {return br.readLine();}

		public double nextDouble() throws IOException
		{
			String x = next();
			StringBuilder sb = new StringBuilder("0");
			double res = 0, f = 1;
			boolean dec = false, neg = false;
			int start = 0;
			if(x.charAt(0) == '-')
			{
				neg = true;
				start++;
			}
			for(int i = start; i < x.length(); i++)
				if(x.charAt(i) == '.')
				{
					res = Long.parseLong(sb.toString());
					sb = new StringBuilder("0");
					dec = true;
				}
				else
				{
					sb.append(x.charAt(i));
					if(dec)
						f *= 10;
				}
			res += Long.parseLong(sb.toString()) / f;
			return res * (neg?-1:1);
		}

		public boolean ready() throws IOException {return br.ready();}

	}

}

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

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */

public class tower {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Task solver = new Task();
        solver.solve(1, in, out);
        out.close();
    }
}

class Task {
    static final int MOD = (int) (1e9 + 7);

    public long sum(long n) {
        return n * (n + 1) / 2;
    }

    int[][] dp;

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        // type the code here
        int r = in.nextInt();
        int g = in.nextInt();
        int tot = r + g;
        int lef = 1, rig = 1000;
        while(lef < rig) {
            int mid = (lef + rig + 1) >> 1;
            if((long) tot < sum(mid)) rig = mid - 1;
            else lef = mid;
        }

        int m = Math.max(r, g);
        r = Math.min(r, g);

        int pake = (int) sum(lef);

        dp = new int[2][r + 2];
        dp[0][0] = 1;
        for(int i = 1; i <= lef; i++) {
            for(int j = 0; j <= r; j++) {
                dp[i & 1][j] = dp[(i & 1)^1][j];
                if(j - i >= 0) dp[i & 1][j] += dp[(i & 1)^1][j - i];
                if(dp[i & 1][j] >= MOD)
                    dp[i & 1][j] -= MOD;
            }
        }

        int ans = 0;
        for(int j = Math.max(pake - m, 0); j <= r; j++) {
            ans += dp[lef & 1][j];
            if(ans >= MOD) ans -= MOD;
        }
        out.println(ans);
    }
}

class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;

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

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

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

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

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

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

/**
 * 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);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        int R;
        int G;
        static final int MOD = (int) (1e9 + 7);

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            R = in.nextInt();
            G = in.nextInt();
            int H = (int) (-1 + Math.sqrt(1 + 8 * (R + G))) / 2;

            int[][] dp = new int[2][R + 1];
            if (G > 0)
                dp[0][R] = 1;
            if (R > 0)
                dp[0][R - 1] = 1;
            int pred = 0, cur = 1;
            for (int h = 2, total = 1; h <= H; h++) {
                total += h;
                for (int r = 0, g = total - R; r <= R; r++, g++) {
                    if (g < 0 || g > G) {
                        dp[cur][r] = 0;
                        continue;
                    } else {
                        dp[cur][r] = dp[pred][r];
                    }
                    if (r + h <= R)
                        dp[cur][r] = (dp[cur][r] + dp[pred][r + h]) % MOD;
                }
                int t = pred;
                pred = cur;
                cur = t;
            }

            long ans = 0;
            for (int i = 0; i < dp[pred].length; i++)
                ans = (ans + dp[pred][i]) % MOD;
            out.println(ans);
        }

    }

    static class InputReader {
        final InputStream is;
        final byte[] buffer = new byte[1024];
        int curCharIdx;
        int nChars;

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

        public int read() {
            if (curCharIdx >= nChars) {
                try {
                    curCharIdx = 0;
                    nChars = is.read(buffer);
                    if (nChars == -1)
                        return -1;
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return buffer[curCharIdx++];
        }

        public int nextInt() {
            int sign = 1;
            int c = skipDelims();
            if (c == '-') {
                sign = -1;
                c = read();
                if (isDelim(c))
                    throw new RuntimeException("Incorrect format");
            }
            int val = 0;
            while (c != -1 && !isDelim(c)) {
                if (!isDigit(c))
                    throw new RuntimeException("Incorrect format");
                val = 10 * val + (c - '0');
                c = read();
            }
            return val * sign;
        }

        private final int skipDelims() {
            int c = read();
            while (isDelim(c)) {
                c = read();
            }
            return c;
        }

        private static boolean isDelim(final int c) {
            return c == ' ' ||
                    c == '\n' ||
                    c == '\t' ||
                    c == '\r' ||
                    c == '\f';
        }

        private static boolean isDigit(final int c) {
            return '0' <= c && c <= '9';
        }

    }
}

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;

public class solver {

    BufferedReader in;
    PrintWriter out;
    StringTokenizer tok;

    static final boolean OJ = System.getProperty("ONLINE_JUDGE") != null;

    void init() throws FileNotFoundException{
        if (OJ){
          in = new BufferedReader(new InputStreamReader(System.in));
          out = new PrintWriter(System.out);
//          in = new BufferedReader(new FileReader("sandwiches.in"));
//          out = new PrintWriter("sandwiches.out");
        }else{
            in = new BufferedReader(new FileReader("input.txt"));
            out = new PrintWriter("output.txt");
        }
    }

    String readString() throws IOException{
        while (tok == null || !tok.hasMoreTokens()){
            tok = new StringTokenizer(in.readLine()," :");
        }
        return tok.nextToken();
    }

    int readInt() throws NumberFormatException, IOException{
        return Integer.parseInt(readString());
    }

    double readDouble() throws NumberFormatException, IOException{
        return Double.parseDouble(readString());
    }

    long readLong() throws NumberFormatException, IOException{
        return Long.parseLong(readString());
    }
    long time;
    void run(){
        try{
            time = System.currentTimeMillis();
            init();
            solve();
            System.err.println(System.currentTimeMillis() - time);
            out.close();
            in.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    long gcd(long a, long b){
        if (a == 0) return b;
        return gcd(b % a, a);
    }

    int getNumberSum(long x){
        long sum = 0;
        while (x > 0){
            sum += x % 10;
            x /= 10;
        }
        return (int)sum;
    }

    int mod(int x, int mod){
        if (x >= mod) return x - mod;
        return x;
    }

    void solve() throws NumberFormatException, IOException{
        int r = readInt();
        int g = readInt();
        int mod = (int)1e9 + 7;
        int n = (int)Math.sqrt(r + g);
        int m = n;
        n+=m;
        int[][] dp = new int[2][r+1];
        dp[0][0] = 1;
        int cur = 0;
        long sum = 0;
        long ans = 0;
        for (int i=0;i<=n;i++){
            int other = 1 - cur;
            Arrays.fill(dp[other], 0);
            int layer = i + 1;
            for (int j=0;j<=r;j++){
                if (sum - j < 0) break;
                if (dp[cur][j] == 0) continue;
                if (sum - j + layer <= g) dp[other][j] = mod(dp[other][j] + dp[cur][j], mod);
                if (j + layer <=r) dp[other][j+layer] = mod(dp[other][j+layer] +dp[cur][j], mod);
            }
            if (i > n - m){
                long res = 0;
                boolean have = false;
                for (int j=0;j<=r;j++){
                    if (dp[other][j] != 0){
                        have = true;
                        res += dp[other][j];
                    }
                }
                if (have) ans = res % mod;
            }
            sum+=layer;
            cur = other;
        }
        out.println(ans);

    }

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

}

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;

public class solver {

    BufferedReader in;
    PrintWriter out;
    StringTokenizer tok;

    static final boolean OJ = System.getProperty("ONLINE_JUDGE") != null;

    void init() throws FileNotFoundException{
        if (OJ){
          in = new BufferedReader(new InputStreamReader(System.in));
          out = new PrintWriter(System.out);
//          in = new BufferedReader(new FileReader("sandwiches.in"));
//          out = new PrintWriter("sandwiches.out");
        }else{
            in = new BufferedReader(new FileReader("input.txt"));
            out = new PrintWriter("output.txt");
        }
    }

    String readString() throws IOException{
        while (tok == null || !tok.hasMoreTokens()){
            tok = new StringTokenizer(in.readLine()," :");
        }
        return tok.nextToken();
    }

    int readInt() throws NumberFormatException, IOException{
        return Integer.parseInt(readString());
    }

    double readDouble() throws NumberFormatException, IOException{
        return Double.parseDouble(readString());
    }

    long readLong() throws NumberFormatException, IOException{
        return Long.parseLong(readString());
    }
    long time;
    void run(){
        try{
            time = System.currentTimeMillis();
            init();
            solve();
            System.err.println(System.currentTimeMillis() - time);
            out.close();
            in.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    long gcd(long a, long b){
        if (a == 0) return b;
        return gcd(b % a, a);
    }

    int getNumberSum(long x){
        long sum = 0;
        while (x > 0){
            sum += x % 10;
            x /= 10;
        }
        return (int)sum;
    }

    int mod(int x, int mod){
        if (x >= mod) return x - mod;
        return x;
    }

    void solve() throws NumberFormatException, IOException{
        int r = readInt();
        int g = readInt();
        int mod = (int)1e9 + 7;
        int n = (int)Math.sqrt(r + g);
        n ++;
        int[][] dp = new int[2][r+1];
        dp[0][0] = 1;
        int cur = 0;
        int sum = 0;
        int ans = 0;
        for (int i=0;i<n;i++){
            int other = 1 - cur;
            Arrays.fill(dp[other], 0);
            int layer = i + 1;
            for (int j=0;j<=r;j++){
                if (sum - j < 0) break;
                if (sum - j + layer <= g)dp[other][j] = mod(dp[other][j] + dp[cur][j], mod);
                if (j + layer <=r) dp[other][j+layer] = mod(dp[other][j+layer] +dp[cur][j], mod);
            }
            if (i > n-3){
                int res = 0;
                boolean have = false;
                for (int j=0;j<=r;j++){
                    if (dp[other][j] != 0) have = true;
                    res = (res + dp[other][j]) % mod;
                }
                if (have) ans = res;
            }
            sum+=layer;
            cur = other;
        }
        out.println(ans);

    }

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

}

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;

public class solver {

    BufferedReader in;
    PrintWriter out;
    StringTokenizer tok;

    static final boolean OJ = System.getProperty("ONLINE_JUDGE") != null;

    void init() throws FileNotFoundException{
        if (OJ){
          in = new BufferedReader(new InputStreamReader(System.in));
          out = new PrintWriter(System.out);
//          in = new BufferedReader(new FileReader("sandwiches.in"));
//          out = new PrintWriter("sandwiches.out");
        }else{
            in = new BufferedReader(new FileReader("input.txt"));
            out = new PrintWriter("output.txt");
        }
    }

    String readString() throws IOException{
        while (tok == null || !tok.hasMoreTokens()){
            tok = new StringTokenizer(in.readLine()," :");
        }
        return tok.nextToken();
    }

    int readInt() throws NumberFormatException, IOException{
        return Integer.parseInt(readString());
    }

    double readDouble() throws NumberFormatException, IOException{
        return Double.parseDouble(readString());
    }

    long readLong() throws NumberFormatException, IOException{
        return Long.parseLong(readString());
    }
    long time;
    void run(){
        try{
            time = System.currentTimeMillis();
            init();
            solve();
            System.err.println(System.currentTimeMillis() - time);
            out.close();
            in.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    long gcd(long a, long b){
        if (a == 0) return b;
        return gcd(b % a, a);
    }

    int getNumberSum(long x){
        long sum = 0;
        while (x > 0){
            sum += x % 10;
            x /= 10;
        }
        return (int)sum;
    }

    int mod(int x, int mod){
        if (x >= mod) return x - mod;
        return x;
    }

    void solve() throws NumberFormatException, IOException{
        int r = readInt();
        int g = readInt();
        int mod = (int)1e9 + 7;
        int n = (int)Math.sqrt(r + g);
        n ++;
        int[][] dp = new int[2][r+1];
        dp[0][0] = 1;
        int cur = 0;
        int sum = 0;
        int ans = 0;
        for (int i=0;i<=n;i++){
            int other = 1 - cur;
            Arrays.fill(dp[other], 0);
            int layer = i + 1;
            for (int j=0;j<=r;j++){
                if (sum - j < 0) break;
                if (sum - j + layer <= g)dp[other][j] = mod(dp[other][j] + dp[cur][j], mod);
                if (j + layer <=r) dp[other][j+layer] = mod(dp[other][j+layer] +dp[cur][j], mod);
            }
            if (i > n-3){
                int res = 0;
                boolean have = false;
                for (int j=0;j<=r;j++){
                    if (dp[other][j] != 0) have = true;
                    res = (res + dp[other][j]) % mod;
                }
                if (have) ans = res;
            }
            sum+=layer;
            cur = other;
        }
        out.println(ans);

    }

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

}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class D {

	static class Scanner{
		BufferedReader br=null;
		StringTokenizer tk=null;
		public Scanner(){
			br=new BufferedReader(new InputStreamReader(System.in));
		}
		public String next() throws IOException{
			while(tk==null || !tk.hasMoreTokens())
				tk=new StringTokenizer(br.readLine());
			return tk.nextToken();
		}
		public int nextInt() throws NumberFormatException, IOException{
			return Integer.valueOf(next());
		}
		public long nextLong() throws NumberFormatException, IOException{
			return Long.valueOf(next());
		}
		public double nextDouble() throws NumberFormatException, IOException{
			return Double.valueOf(next());
		}
	}

	static int R, G;
	static int mod = 1000000009;
	static int[][] dp;

	static int gastado(int level){
		int ret = level * (level + 1);
		return ret/2;
	}

	static int getlevel(){
		int maxlevel = 0;
		while(gastado(maxlevel) <= R + G)
			maxlevel++;
		return maxlevel - 1;
	}

	public static void main(String args[]) throws NumberFormatException, IOException{
		Scanner sc = new Scanner();
		R = sc.nextInt();
		G = sc.nextInt();
		dp = new int[2][R + 1];
		int h = getlevel();
		for(int i = 0; i <= R; i++)
			dp[h & 1][i] = 1;
		for(int i = h - 1; i >= 0; i--){
			for(int r = 0; r <= Math.min(R, gastado(i)); r++){
				int quedarojo = R - r;
				int quedaverde = G - (gastado(i) - r);
				if (quedaverde < 0)
					continue;
				int current = i + 1;
				dp[i & 1][r] = 0;
				if (quedarojo >= current)
					dp[i & 1][r] = (dp[i & 1][r] + dp[(i + 1)&1][r + current]) % mod;
				if (quedaverde >= current)
					dp[i & 1][r] = (dp[i & 1][r] +  dp[(i + 1)&1][r]) % mod;
				//System.out.print(i +" " + r + "," + dp[i % 2][r] + " - ");
			}
			//System.out.println();
		}
		System.out.println(dp[0][0]);
	}

}

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

public class Main {

	static long[][] dp;

	public static void main(String[] args) throws IOException{
        Scanner scan = new Scanner(System.in);
        int r = scan.nextInt();
        int g = scan.nextInt();
        long h = 1000000007;
        int size = r + g + 5;
        dp = new long[2][size];
        Arrays.fill(dp[0], 0);
        Arrays.fill(dp[1], 0);
        dp[0][0] = 1;
        dp[1][0] = 1;
        int max = 0;
        for(int i = 1; i < size; i++) {
        	int red = i % 2;
        	int green = 1 - red;

        	while(((i+1) * (i+1) + (i+1)) / 2 <= r + g) {
        		i++;
//        		height = (i * i + i) / 2;
        	}
        	int height = (i * i + i) / 2;
        	if(height > r + g) break;
        	for(int j = 1; j <= height; j++) {
        		dp[red][j] = dp[green][j];
        		dp[red][j] %= h;
        		if(j >= i) dp[red][j] += dp[green][j-i];
        		dp[red][j] %= h;
        	}
        	max = i;
        }
        long count = 0;
        long height = (max * max + max) / 2;
        for(int i = 0; i <= r; i++){
        	if(height - i > g) continue;
        	int color = max % 2;
        	count += dp[color][i];
        	count %= h;
        }
		System.out.println(count);
	}
}

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

public class Main {

	static long[][] dp;

	public static void main(String[] args) throws IOException{
        Scanner scan = new Scanner(System.in);
        int r = scan.nextInt();
        int g = scan.nextInt();
        long h = 1000000007;
        int size = r + g + 5;
        dp = new long[2][size];
        Arrays.fill(dp[0], 0);
        Arrays.fill(dp[1], 0);
        dp[0][0] = 1;
        dp[1][0] = 1;
        int max = 0;
        for(int i = 1; i < size; i++) {
        	int red = i % 2;
        	int green = 1 - red;
        	int height = (i * i + i) / 2;
        	while(height <= r + g) {
        		i++;
        		height = (i * i + i) / 2;
        	}
        	i--;
        	if(height > r + g) break;
        	for(int j = 1; j <= height; j++) {
        		dp[red][j] = dp[green][j];
        		dp[red][j] %= h;
        		if(j >= i) dp[red][j] += dp[green][j-i];
        		dp[red][j] %= h;
        	}
        	max = i;
        }
        long count = 0;
        long height = (max * max + max) / 2;
        for(int i = 0; i <= r; i++){
        	if(height - i > g) continue;
        	int color = max % 2;
        	count += dp[color][i];
        	count %= h;
        }
		System.out.println(count);
	}
}

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

import static java.lang.Math.*;

public class Solution implements Runnable {

	final int MOD = (int)(1e9) + 7;

	void solve() throws Exception {
		int r = sc.nextInt();
		int g = sc.nextInt();
		int lf = 0, rg = 700;
		while (rg - lf > 1) {
			int md = (lf + rg) / 2;
			int rr = r;
			int gg = g;
			int i = 0;
			for (i = md; i >= 1 && (rr >= i || gg >= i); --i) {
				if (rr >= i)
					rr -= i;
				else
					gg -= i;
			}
			if (i == 0) {
				lf = md;
			} else {
				rg = md;
			}
		}
		rg--;
		int dp[][] = new int[2][g + 1];
		dp[0][0] = 1;
		for (int lvl = 0, sm = 0; lvl < rg; lvl++) {
			int X = (lvl & 1);
			int Y = (X ^ 1);
			Arrays.fill(dp[Y], 0);
			int cur = rg - lvl;
			for (int i = 0; i <= min(sm, g); i++) {
				if (dp[X][i] > 0) {
					if (i + cur <= g) {
						dp[Y][i + cur] += dp[X][i];
						if (dp[Y][i + cur] >= MOD)
							dp[Y][i + cur] -= MOD;
					}
					if (sm - i + cur <= r) {
						dp[Y][i] += dp[X][i];
						if (dp[Y][i] >= MOD)
							dp[Y][i] -= MOD;
					}
				}
			}
			sm += cur;
		}
		int ans = 0;
		for (int i = 0; i <= g; i++) {
			ans = ans + dp[rg & 1][i];
			if (ans >= MOD)
				ans -= MOD;
		}
		out.println(ans);
	}

	BufferedReader in;
	PrintWriter out;
	FastScanner sc;

	static Throwable throwable;

	public void run() {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
			//in = new BufferedReader(new FileReader(".in"));
			//out = new PrintWriter(".out");
			sc = new FastScanner(in);
			solve();
		} catch (Exception e) {
			throwable = e;
		} finally {
			out.close();
		}
	}

	public static void main(String[] args) throws Throwable {
		Thread thread = new Thread(null, new Solution(), "", (1 << 26));
		thread.start();
		thread.join();
		thread.run();
		if (Solution.throwable != null)
			throw Solution.throwable;
	}

}

class FastScanner {
	BufferedReader reader;
	StringTokenizer strTok;

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

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

	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.Scanner;

public class Node
{
	public static void main(String[] args) {

		Scanner sc=new Scanner(System.in);
		int red=sc.nextInt();
		int green=sc.nextInt();
		int height=0;
		for(;((height)*(height+1)/2)<=red+green;height++);
		height--;
		int[][] dp=new int[height+1][red+1];
		//dp[i][j] is number of ways of making towers of height i with j red balls and
		dp[0][0]=1;

		for(int i=1;i<=height;i++)
		{
			for(int j=i;j<=Math.min(red,(i*(i+1))/2);j++)
			{
				dp[i][j]=dp[i][j]+dp[i-1][j-i];
			}

		}
		int sum=0;
		for(int i=0;i<=red;i++)
			sum+=dp[height][i];
		System.out.println(sum);
	}

}

import java.util.Scanner;

public class Node
{
	public static void main(String[] args) {

		int MOD=(int) (1e9+7);
		Scanner sc=new Scanner(System.in);
		int red=sc.nextInt();
		int green=sc.nextInt();
		int height=0;
		for(;((height)*(height+1)/2)<=red+green;height++);
		height--;

		int[] dp=new int[red+1];
		dp[0]=1;
		for(int i=1;i<=height;i++)
		{
			for(int k=Math.min(i*(i+1)/2, red);k>=i;k--)
			{
				dp[k]=dp[k]+dp[k-i];
			}
		}
		int ans=0;
		int sum=height*(height+1)/2;
		for(int i=Math.max(0,sum-red);i<=Math.min(sum, green);i++)
		{
			ans=(ans+dp[sum-i])%MOD;
		}
		System.out.println(ans);
	}

}

import java.util.Scanner;

public class Node
{
	public static void main(String[] args) {

		int MOD=(int) (1e9+7);
		Scanner sc=new Scanner(System.in);
		int red=sc.nextInt();
		int green=sc.nextInt();
		int height=0;
		for(;((height)*(height+1)/2)<=red+green;height++);
		height--;

		int[] dp=new int[red+1];
		dp[0]=1;
		for(int i=1;i<=height;i++)
		{
			for(int k=i;k<=Math.min(i*(i+1)/2, red);k++)
			{
				dp[k]=dp[k]+dp[k-i];
			}
		}
		int ans=0;
		int sum=height*(height+1)/2;
		for(int i=Math.max(0,sum-red);i<=Math.min(sum, green);i++)
		{
			ans=(ans+dp[sum-i])%MOD;
		}
		System.out.println(ans);
	}

}

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

public class D {
	FastScanner in = new FastScanner(System.in);
	PrintWriter out = new PrintWriter(System.out);

	int MOD = 1000000007;

	int[] dp;

	int calcH(int x) {
		for (int i = 0, sum = 0; i < 1000000; i++) {
			if (sum > x) return i - 1;

			sum += i + 1;
		}
		return -1;
	}

	int doit(int minColor, int h) {
		Arrays.fill(dp, 0);

		dp[0] = 1;
		for (int i = 1; i <= h; i++) {
			for (int j = minColor - 2; j >= 0; j--) {
				if (i + j <= minColor) dp[i+j] += dp[j];
			}
		}

		return dp[minColor];
	}

	public void run() {
		int r = in.nextInt(), g = in.nextInt();
		int sum = r + g;

		int h = calcH(sum);
		int blockNum = (h * (h + 1)) / 2;

		dp = new int[1000000];

		if (r < g) {
			int temp = r;
			r = g;
			g = temp;
		}

		int maxR = Math.min(r, blockNum);
		int minG = blockNum - maxR;

		long res = 0;
		for (int rr = maxR, gg = minG; rr >= 0 && gg <= g; rr--, gg++) {
			res = res + doit(Math.min(rr, gg), h);
			if (res > MOD) res -= MOD;
		}
		System.out.println(res);

		out.close();
	}

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

	public void mapDebug(int[][] a) {
		System.out.println("--------map display---------");

		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j < a[i].length; j++) {
				System.out.printf("%3d ", a[i][j]);
			}
			System.out.println();
		}

		System.out.println("----------------------------");
		System.out.println();
	}

	public void debug(Object... obj) {
		System.out.println(Arrays.deepToString(obj));
	}

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

		public FastScanner(InputStream stream) {
			this.stream = stream;
			//stream = new FileInputStream(new File("dec.in"));

		}

		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++];
		}

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

		boolean isEndline(int c) {
			return c == '\n' || c == '\r' || c == -1;
		}

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

		int[] nextIntArray(int n) {
			int[] array = new int[n];
			for (int i = 0; i < n; i++)
				array[i] = nextInt();

			return array;
		}

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

		long[] nextLongArray(int n) {
			long[] array = new long[n];
			for (int i = 0; i < n; i++)
				array[i] = nextLong();

			return array;
		}

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

		double[] nextDoubleArray(int n) {
			double[] array = new double[n];
			for (int i = 0; i < n; i++)
				array[i] = nextDouble();

			return array;
		}

		String next() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		String[] nextStringArray(int n) {
			String[] array = new String[n];
			for (int i = 0; i < n; i++)
				array[i] = next();

			return array;
		}

		String nextLine() {
			int c = read();
			while (isEndline(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isEndline(c));
			return res.toString();
		}
	}
}

import java.util.Scanner;

public class Gela {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int r = sc.nextInt(), g = sc.nextInt();
        int bound = 501;
        int[][] dp = new int[bound][];
        for(int i=0; i<bound; i++) {
            int sz = (i*i + i) / 2 + 1;
            dp[i] = new int[sz];
        }
        int h = getHeight(r, g);
        // dp(h, n) = dp(h-1, n) + dp(h-1, n-h);
        dp[1][1] = 1;
        dp[1][0] = 1;
        int P = 1000000007;
    //  System.out.println(h);
        for(int x=2; x<=h; x++) {
            int b = (x*x+x)/2;
            dp[x][0] = 1;
            for(int n=1; n<=b; n++) {
                dp[x][n] = ((n<dp[x-1].length ? dp[x-1][n] : 0) + ((n>=x && n-x < dp[x-1].length) ? dp[x-1][n-x] : 0)) % P;
            }
        }
        long res = 0;
        long needed = (h*h+h)/2;
        for(int x=0; x<=r; x++) {
            long y = needed - x;
            if(y > g || y<0) continue;
            res += (x<dp[h].length ? dp[h][x] : 0);
        }
        System.out.println(res % P);
    }

    static int getHeight(int r, int g) {
        for(int h=500; h>=0; h--) {
            if(h*h + h <= 2*r + 2*g) return h;
        }
        return -1;
    }

}

import java.util.Scanner;

public class Gela {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int r = sc.nextInt(), g = sc.nextInt();
        int bound = 501;
        int[][] dp = new int[bound][];
        for(int i=0; i<bound; i++) {
            int sz = (i*i + i) / 2 + 1;
            dp[i] = new int[sz];
        }
        int h = getHeight(r, g);
        // dp(h, n) = dp(h-1, n) + dp(h-1, n-h);
        dp[1][1] = 1;
        dp[1][0] = 1;
        int P = 1000000007;
        System.out.println(h);
        for(int x=2; x<=h; x++) {
            int b = (x*x+x)/2;
            dp[x][0] = 1;
            for(int n=1; n<=b; n++) {
                dp[x][n] = ((n<dp[x-1].length ? dp[x-1][n] : 0) + ((n>=x && n-x < dp[x-1].length) ? dp[x-1][n-x] : 0)) % P;
            }
        }
        long res = 0;
        long needed = (h*h+h)/2;
        for(int x=0; x<=r; x++) {
            long y = needed - x;
            if(y > g || y<0) continue;
            res += (x<dp[h].length ? dp[h][x] : 0);
        }
        System.out.println(res % P);
    }

    static int getHeight(int r, int g) {
        for(int h=500; h>=0; h--) {
            if(h*h + h <= 2*r + 2*g) return h;
        }
        return -1;
    }

}

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

public class Main{
    final boolean isFileIO = false;
    BufferedReader in;
    PrintWriter out;
    StringTokenizer st = new StringTokenizer("");
    String delim = " ";

    public static void main(String[] args) throws IOException {
        Main m = new Main();
        m.initIO();
        m.solve();
        m.in.close();
        m.out.close();
    }

    public void initIO() throws IOException {
        if(!isFileIO) {
            in = new BufferedReader(new InputStreamReader(System.in));
            out = new PrintWriter(System.out);
        } else {
            in = new BufferedReader(new FileReader("input.txt"));
            out = new PrintWriter("output.txt");
        }
    }

    String nextToken() throws IOException {
        if(!st.hasMoreTokens()) {
            st = new StringTokenizer(in.readLine());
        }
        return st.nextToken(delim);
    }

    String readLine() throws IOException {
        return in.readLine();
    }

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

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

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

    boolean[] sum;
    int r, g;
    public void solve() throws IOException {
        r = nextInt(); g = nextInt();
        int left = 1;
        sum = new boolean[r + 1];
        int right = (int)Math.sqrt(1 + 8 * (r + g)) + 1;
        int mid;
        while(left < right) {
            mid = left + (right - left) / 2;
            if(isOk(mid)) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        if(!isOk(left)) {
            left--;
        }
        out.println(left);
        int all = (left * (left + 1)) / 2;
        long[] dp = new long[all + 1];
        dp[0] = 1;
        long mod = 1_000_000_007;
        for(int i = 1; i <= left; i++) {
            for(int j = all; j >= i; j--) {
                if(j <= r) {
                    dp[j] = (dp[j] + dp[j - i]) % mod;
                }
            }
        }
        long ans = 0;
        for(int i = 0; i <= all; i++) {
            if(all - i <= g) {
                ans = (ans + dp[i]) % mod;
            }
        }
        out.println(ans);
    }

    boolean isOk(int h) {
        int n = sum.length;
        for(int i = 0; i < n; i++) {
            sum[i] = false;
        }
        sum[0] = true;
        for(int i = 1; i <= h; i++) {
            for(int j = n - 1; j >= i; j--) {
                sum[j] = sum[j - i];
            }
        }
        int all = (h * (h + 1)) / 2;
        for(int i = 0; i < n; i++) {
            if(sum[i]) {
                if(all - i <= g) {
                    return true;
                }
            }
        }
        return false;
    }

}

class Utils {

    public static long binpow(long a, long exp, long mod) {
        if(exp == 0) {
            return 1;
        }
        if(exp % 2 == 0) {
            long temp = binpow(a, exp / 2, mod);
            return (temp * temp) % mod;
        } else {
            return (binpow(a, exp - 1, mod) * a) % mod;
        }
    }

    public static long inv(long a, long mod) {
        return binpow(a, mod - 2, mod);
    }

    public static long addmod(long a, long b, long mod) {
        return (a + b + 2 * mod) % mod;
    }
}

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

public class Main{
    final boolean isFileIO = false;
    BufferedReader in;
    PrintWriter out;
    StringTokenizer st = new StringTokenizer("");
    String delim = " ";

    public static void main(String[] args) throws IOException {
        Main m = new Main();
        m.initIO();
        m.solve();
        m.in.close();
        m.out.close();
    }

    public void initIO() throws IOException {
        if(!isFileIO) {
            in = new BufferedReader(new InputStreamReader(System.in));
            out = new PrintWriter(System.out);
        } else {
            in = new BufferedReader(new FileReader("input.txt"));
            out = new PrintWriter("output.txt");
        }
    }

    String nextToken() throws IOException {
        if(!st.hasMoreTokens()) {
            st = new StringTokenizer(in.readLine());
        }
        return st.nextToken(delim);
    }

    String readLine() throws IOException {
        return in.readLine();
    }

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

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

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

    boolean[] sum;
    int r, g;
    public void solve() throws IOException {
        r = nextInt(); g = nextInt();
        int left = 1;
        sum = new boolean[r + 1];
        int right = (int)Math.sqrt(r + g) + 1;
        int mid;
        while(left < right) {
            mid = left + (right - left) / 2;
            if(isOk(mid)) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        if(!isOk(left)) {
            left--;
        }
        int all = (left * (left + 1)) / 2;
        long[] dp = new long[all + 1];
        dp[0] = 1;
        long mod = 1_000_000_007;
        for(int i = 1; i <= left; i++) {
            for(int j = all; j >= i; j--) {
                if(j <= r) {
                    dp[j] = (dp[j] + dp[j - i]) % mod;
                }
            }
        }
        long ans = 0;
        for(int i = 0; i <= all; i++) {
            if(all - i <= g) {
                ans = (ans + dp[i]) % mod;
            }
        }
        out.println(ans);
    }

    boolean isOk(int h) {
        int n = sum.length;
        for(int i = 0; i < n; i++) {
            sum[i] = false;
        }
        sum[0] = true;
        for(int i = 1; i <= h; i++) {
            for(int j = n - 1; j >= i; j--) {
                sum[j] = sum[j - i];
            }
        }
        int all = (h * (h + 1)) / 2;
        for(int i = 0; i < n; i++) {
            if(sum[i]) {
                if(all - i <= g) {
                    return true;
                }
            }
        }
        return false;
    }

}

class Utils {

    public static long binpow(long a, long exp, long mod) {
        if(exp == 0) {
            return 1;
        }
        if(exp % 2 == 0) {
            long temp = binpow(a, exp / 2, mod);
            return (temp * temp) % mod;
        } else {
            return (binpow(a, exp - 1, mod) * a) % mod;
        }
    }

    public static long inv(long a, long mod) {
        return binpow(a, mod - 2, mod);
    }

    public static long addmod(long a, long b, long mod) {
        return (a + b + 2 * mod) % mod;
    }
}

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

public class cf273D {
    public static void main(String[] args) throws Exception {
    	// BufferedReader in = new BufferedReader(new FileReader("cf273D.in"));
    	BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

		String str = in.readLine();
		int r = Integer.parseInt(str.substring(0, str.indexOf(" ")));
		int g = Integer.parseInt(str.substring(str.indexOf(" ") + 1));

		int h = 1;
		while((h + 1) * (h + 2) / 2 <= r + g) {
			h++;
		}
		int max = h * (h + 1) / 2;
		long[] greens = new long[g + 1];
		greens[0] = 1;
		for(int i = 1; i <= h; i++) {
			int size = Math.min(g, i * (i + 1) / 2);
			int min = Math.max(i, Math.min(size - r, g - max + size));
			for(int j = size; j >= min; j--) {
				greens[j] += greens[j - i];
			}
		}
		long total = 0;
		for(int i = Math.max(0, max - r); i <= g; i++) {
			total += greens[i];
		}
		System.out.println(total);
	}
}

import java.util.Scanner;
import java.io.PrintWriter;

public class d {
	private static final int maxh = 1000;
	private static final long mod = 1000000000 + 7;
	private static int sumx(int k){
		int l = 0;
		int r = maxh;
		while (r - l > 1){
			int m = (r + l) >> 1;
			if (m * (m + 1) > 2 * k)
				r = m;
			else if (m * (m + 1) < 2 * k)
				l = m;
			else
				return m;
		}
		return l;
	}
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		PrintWriter out = new PrintWriter(System.out);
		int r = 0, g = 0;
		r = in.nextInt();
		g = in.nextInt();
		// long tstart = System.currentTimeMillis();
		int h = sumx(r + g);
		int red[][] = new int[2][r + 1];
		int green[][] = new int[2][r + 1];
		for (int i = 0; i < r + 1; i++){
			red[0][i] = 0;
			green[0][i] = 0;
		}
		red[0][1] = 1;
		green[0][0] = 1;
		int cur = 1;
		for (int i = 1; i < h; i++){
			for (int j = 0; j <= i; j++){
				green[cur][j] = red[1 - cur][j] + green[1 - cur][j];
				if (green[cur][j] >= mod)
					green[cur][j] -= mod;
			}
			for (int j = i + 1; j <= r; j++){
				red[cur][j] = red[1 - cur][j - i - 1] + green[1 - cur][j - i - 1];
				green[cur][j] = red[1 - cur][j] + green[1 - cur][j];
				if (red[cur][j] >= mod)
					red[cur][j] -= mod;
				if (green[cur][j] >= mod)
					green[cur][j] -= mod;
			}
			cur = 1 - cur;
		}
		int ans = 0;
		for (int i = Math.max(0, h * (h + 1) / 2 - g); i <= r; i++){
			ans = ans + red[1 - cur][i];
			if (ans >= mod)
				ans -= mod;
			ans = ans + green[1 - cur][i];
			if (ans >= mod)
				ans -= mod;
		}
		out.println(ans);
		// long tstop = System.currentTimeMillis();
		// out.println(tstop - tstart);
		in.close();
		out.close();
	}
}

import java.util.Scanner;
import java.io.PrintWriter;

public class d {
	private static final int maxh = 1000;
	private static final long mod = 1000000000 + 7;
	private static int sumx(int k){
		int l = 0;
		int r = maxh;
		while (r - l > 1){
			int m = (r + l) >> 1;
			if (m * (m + 1) > 2 * k)
				r = m;
			else if (m * (m + 1) < 2 * k)
				l = m;
			else
				return m;
		}
		return l;
	}
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		PrintWriter out = new PrintWriter(System.out);
		int r = 0, g = 0;
		r = in.nextInt();
		g = in.nextInt();
		if (r < g){
			int t = r;
			r = g;
			g = t;
		}
		int h = sumx(r + g);
		int dp[][] = new int[2][r + 1];
		for (int i = 0; i < r + 1; i++)
			dp[0][i] = 0;
		dp[0][0] = dp[0][1] = 1;
		int cur = 1;
		for (int i = 1; i < h; i++){
			for (int j = 0; j <= i; j++){
				dp[cur][j] = dp[cur ^ 1][j] + dp[cur ^ 1][j];
				if (dp[cur][j] >= mod)
					dp[cur][j] -= mod;
			}
			for (int j = i + 1; j <= r; j++){
				dp[cur][j] = dp[cur ^ 1][j - i - 1] + dp[cur ^ 1][j];
				if (dp[cur][j] >= mod)
					dp[cur][j] -= mod;
			}
			cur = cur ^ 1;
		}
		long ans = 0;
		for (int i = Math.max(0, h * (h + 1) / 2 - g); i <= r; i++){
			ans += (long)dp[cur ^ 1][i];
		}
		ans %= mod;
		out.println(ans);
		in.close();
		out.close();
	}
}

import java.util.Scanner;
import java.io.PrintWriter;

public class d {
	private static final int maxh = 1000;
	private static final long mod = 1000000000 + 7;
	private static int sumx(int k){
		int l = 0;
		int r = maxh;
		while (r - l > 1){
			int m = (r + l) >> 1;
			if (m * (m + 1) > 2 * k)
				r = m;
			else if (m * (m + 1) < 2 * k)
				l = m;
			else
				return m;
		}
		return l;
	}
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		PrintWriter out = new PrintWriter(System.out);
		int r = 0, g = 0;
		r = in.nextInt();
		g = in.nextInt();
		if (r < g){
			int t = r;
			r = g;
			g = t;
		}
		int h = sumx(r + g);
		int dp[][] = new int[2][r + 1];
		for (int i = 0; i < r + 1; i++)
			dp[0][i] = 0;
		dp[0][1] = 1;
		int cur = 1;
		for (int i = 1; i < h; i++){
			for (int j = 0; j <= i; j++){
				dp[cur][j] = dp[cur ^ 1][j] + dp[cur ^ 1][j];
				if (dp[cur][j] >= mod)
					dp[cur][j] -= mod;
			}
			for (int j = i + 1; j <= r; j++){
				dp[cur][j] = dp[cur ^ 1][j - i - 1] + dp[cur ^ 1][j];
				if (dp[cur][j] >= mod)
					dp[cur][j] -= mod;
			}
			cur = cur ^ 1;
		}
		long ans = 0;
		for (int i = Math.max(0, h * (h + 1) / 2 - g); i <= r; i++){
			ans += (long)dp[cur ^ 1][i];
		}
		ans %= mod;
		out.println(ans);
		in.close();
		out.close();
	}
}

import java.util.*;
import java.math.*;
import java.io.*;
 import java.text.DecimalFormat;
public class Main{
    static int[] arr;
    static String h;
    static int mod=1000000007 ;
    public static void main(String[] args)  throws IOException {
        s.init(System.in);
        int r=s.nextInt();
        int g=s.nextInt();
        int h=(-1+(int)Math.sqrt(1+8*(r+g)))/2;
        int[]dp=new int[r+1];
        dp[0]=1;

        for(int k=1;k<=h;k++){
            for(int i=0;i<=r;i++){

                if(i+k+1<=r)
                    dp[i+k+1]=(dp[i+k+1]+dp[i])%mod;;

            }

        }
        int ans=0;
        for(int i=0;i<=r;i++){
            if((h*(h+1))/2-i<=g)
                ans+=dp[i];
            ans%=mod;
        }
        System.out.println(ans);
    }

   public static class s {
        static BufferedReader reader;
        static StringTokenizer tokenizer;

        /** call this method to initialize reader for InputStream */
        static void init(InputStream input) {
            reader = new BufferedReader(
                        new InputStreamReader(input) );
            tokenizer = new StringTokenizer("");
        }

        /** get next word */
        static String next() throws IOException {
            while ( ! tokenizer.hasMoreTokens() ) {
                //TODO add check for eof if necessary
                tokenizer = new StringTokenizer(
                    reader.readLine() );
            }
            return tokenizer.nextToken();
        }

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

        static double nextDouble() throws IOException {
            return Double.parseDouble( next() );
        }
        static long nextLong() throws IOException {
            return Long.parseLong( next() );
        }

    }
}

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

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

	FastReader in = new FastReader();
	PrintWriter out = new PrintWriter(System.out);
	void run(){
		work();
		out.flush();
	}
	long mod=1000000007;
	long gcd(long a,long b) {
		return a==0?b:b>=a?gcd(b%a,a):gcd(b,a);
	}

	void work() {
		int n=in.nextInt(),m=in.nextInt();
		if(n>m) {
			int t=m;
			m=n;
			n=t;
		}
		int s=n+m;
		int k=(int)Math.sqrt(s*2);
		if(k*(k+1)>s*2) {
			k--;
		}
		k=Math.min(k, n);
		s=(1+k)*k/2;
		long[][] dp=new long[k+1][n+1];
		dp[0][0]=1;
		long ret=0;
		if(m>=s) {
			ret++;
		}
		for(int j=1;j<=n;j++) {
			for(int i=1;i<=j&&i<=k;i++) {//最大为j
				dp[i][j]+=dp[Math.min(j-i, i-1)][j-i];
				dp[i][j]%=mod;
				if(s-j<=m) {
					ret+=dp[i][j];
					ret%=mod;
				}
			}
			for(int i=1;i<=k;i++) {
				dp[i][j]+=dp[i-1][j];
				dp[i][j]%=mod;
			}
		}
		out.println(ret);
	}
}

class FastReader
{
	BufferedReader br;
	StringTokenizer st;

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

	public String next()
	{
		while(st==null || !st.hasMoreElements())//回车，空行情况
		{
			try {
				st = new StringTokenizer(br.readLine());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return st.nextToken();
	}

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

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

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class D {
    public static final int MOD = 1000000007;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int r = sc.nextInt();
        int g = sc.nextInt();
        Map<Pair, Integer> cache = new HashMap<Pair, Integer>();
        int h = maxHeight(r + g);
        int k;
//      do {
            cache.clear();
            k = dfs(h, 0, 0, r, g, cache);
            h--;
//      } while (k < 1);
        System.out.println(k);
    }

    private static int maxHeight(int blocks) {
        int c = blocks << 1;
        int d = (int)Math.sqrt(1 + 4 * c);
        int h = (d - 1) / 2;
        return h;
    }

    private static int dfs(int n, int curR, int curG, int r, int g, Map<Pair, Integer> cache) {
        Pair cur = new Pair(curR > curG ? curR : curG, curR > curG ? curG : curR);
        int res;
        if (n == 0) {
            res = 1;
        } else {
            Integer prevRes = cache.get(cur);
            if (prevRes != null) {
                return prevRes;
            }

            int res1 = curR + n <= r ? dfs(n - 1, curR + n, curG, r, g, cache) : -1;
            int res2 = curG + n <= g ? dfs(n - 1, curR, curG + n, r, g, cache) : -1;
            res = res1 < 0 && res2 < 0 ? -1 : (((res1 > 0 ? res1 : 0) + (res2 > 0 ? res2 : 0)) % MOD);
        }

        cache.put(cur, res);
        return res;
    }

    private static class Pair {
        int a;
        int b;

        private Pair(int a, int b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + a;
            result = prime * result + b;
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Pair other = (Pair) obj;
            if (a != other.a)
                return false;
            if (b != other.b)
                return false;
            return true;
        }

    }
}

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class D {
    public static final int MOD = 1000000007;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int r = sc.nextInt();
        int g = sc.nextInt();
        Map<Pair, Integer> cache = new HashMap<Pair, Integer>();
        int h = maxHeight(r + g);
        int k = dfs(h, 0, 0, r, g, cache);
        System.out.println(k);
    }

    private static int maxHeight(int blocks) {
        int h = (int)Math.sqrt(2 * blocks);
        return h;
    }

    private static int dfs(int n, int curR, int curG, int r, int g, Map<Pair, Integer> cache) {
        Pair cur = new Pair(curR > curG ? curR : curG, curR > curG ? curG : curR);
        int res;
        if (n == 0) {
            res = 1;
        } else {
            Integer prevRes = cache.get(cur);
            if (prevRes != null) {
                return prevRes;
            }

            int res1 = curR + n <= r ? dfs(n - 1, curR + n, curG, r, g, cache) : -1;
            int res2 = curG + n <= g ? dfs(n - 1, curR, curG + n, r, g, cache) : -1;
            res = res1 < 0 && res2 < 0 ? -1 : (((res1 > 0 ? res1 : 0) + (res2 > 0 ? res2 : 0)) % MOD);
        }

        cache.put(cur, res);
        return res;
    }

    private static class Pair {
        int a;
        int b;

        private Pair(int a, int b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + a;
            result = prime * result + b;
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Pair other = (Pair) obj;
            if (a != other.a)
                return false;
            if (b != other.b)
                return false;
            return true;
        }

    }
}

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class P478D
{
	public static void main(String[] args) {
		try {
			BufferedReader fin = new BufferedReader(new InputStreamReader(System.in));
			StringTokenizer sc = new StringTokenizer(fin.readLine());
			int r = Integer.parseInt(sc.nextToken());
			int g = Integer.parseInt(sc.nextToken());
			fin.close();

			int low = Math.min(r, g);
			int high = Math.max(r, g);
			long mod = 1000000007;
			long[] c = new long[low + 1];
			int h = (int) Math.sqrt(2 * (r + g));
			if (h * (h + 1) > 2 * (r + g)) {
				h--;
			}
			int total = h * (h + 1) / 2;

			c[0] = c[1] = 1;
			for (int i = 2, m = 2; i <= h; m += i, i++) {
				for (int j = m - 1; j >= 0; j--) {		// decrement so that current level will not be counted again
					if (j + i <= low) {
						c[j + i] += c[j];
						c[j + i] %= mod;
					}
				}
//				System.out.println(i + ": " + Arrays.toString(c));
			}
//			System.out.println(h + ": " + Arrays.toString(c));

			long sum = 0;
			for (int i = total - high; i < low + 1; i++) {
				sum += c[i];
			}
			System.out.println(Long.toString(sum));
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.exit(0);
	}
}

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class RedGreenTowers478D
{
	public static void main(String[] args) {
		try {
			BufferedReader fin = new BufferedReader(new InputStreamReader(System.in));
			StringTokenizer sc = new StringTokenizer(fin.readLine());
			int r = Integer.parseInt(sc.nextToken());
			int g = Integer.parseInt(sc.nextToken());
			fin.close();

			int low = Math.min(r, g);
			int high = Math.max(r, g);
			long mod = 1000000007;
			long[] c = new long[low + 1];
			int h = (int) Math.sqrt(2 * (r + g));
			if (h * (h + 1) > 2 * (r + g)) {
				h--;
			}
			int total = h * (h + 1) / 2;
//			System.out.println("t: " + (total - high) + ", " + low);

			c[0] = c[1] = 1;
			for (int i = 2, m = 2; i <= h; m += i, i++) {
				for (int j = m - 1; j >= 0; j--) {		// decrement so that current level will not be counted again
					if (j + i <= low) {
						c[j + i] += c[j];
						c[j + i] %= mod;
					}
				}
//				System.out.println(i + ": " + Arrays.toString(c));
			}
//			System.out.println(h + ": " + Arrays.toString(c));

			long sum = 0;
			for (int i = Math.max(0, total - high); i < low + 1; i++) {
				sum += c[i];
				sum %= mod;
			}
			System.out.println(Long.toString(sum));
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.exit(0);
	}
}

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class RedGreenTowers478D
{
	public static void main(String[] args) {
		try {
			BufferedReader fin = new BufferedReader(new InputStreamReader(System.in));
			StringTokenizer sc = new StringTokenizer(fin.readLine());
			int r = Integer.parseInt(sc.nextToken());
			int g = Integer.parseInt(sc.nextToken());
			fin.close();

			int low = Math.min(r, g);
			int high = Math.max(r, g);
			long mod = 1000000007;
			long[] c = new long[low + 1];
			int h = (int) Math.sqrt(2 * (r + g));
			if (h * (h + 1) > 2 * (r + g)) {
				h--;
			}
			int total = h * (h + 1) / 2;
//			System.out.println("t: " + (total - high) + ", " + low);

			c[0] = c[1] = 1;
			for (int i = 2, m = 2; i <= h; m += i, i++) {
				for (int j = m - 1; j >= 0; j--) {		// decrement so that current level will not be counted again
					if (j + i <= low) {
						c[j + i] += c[j];
						c[j + i] %= mod;
					}
				}
//				System.out.println(i + ": " + Arrays.toString(c));
			}
//			System.out.println(h + ": " + Arrays.toString(c));

			long sum = 0;
			for (int i = Math.max(0, total - high); i < low + 1; i++) {
				sum += c[i];
			}
			System.out.println(Long.toString(sum));
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.exit(0);
	}
}

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

/*
public class _478D {

}

 */

class node2
{
	int r;
	//int g;
	int h;

	@Override
	public String toString() {
		return "node [r=" + r + ", h=" + h + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + h;
		result = prime * result + r;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		node2 other = (node2) obj;
		if (h != other.h)
			return false;
		if (r != other.r)
			return false;
		return true;
	}

}

public class _478D {
	private static PrintWriter printWriter;

	Map<node2, Integer> nh = new HashMap<node2, Integer>();

	//int[][] dp = new int[200001][2];

	node2 inode = new node2();

	int mod = 1000000007;
	int ir = 0, ig = 0, ih = 0, ub = 0;

	public void solve() throws FileNotFoundException {
		InputStream inputStream = System.in;

		InputHelper inputHelper = new InputHelper(inputStream);

		PrintStream out = System.out;

		//actual solution

		int r = inputHelper.readInteger();
		int g = inputHelper.readInteger();

		int h;

		for(h = 1; ; h++)
		{
			if(((h * (h + 1)) / 2) > r + g)
					break;
		}

		h--;

		ub = ((h * (h + 1)) / 2);

		ir = r;
		ig = g;
		ih = h;

		System.out.println(rec(r, h));
		//end here

		//printWriter.close();
	}

	private long rec(int r, int h)
	{
		if(h < 1)
			return 0;

		int u = (ub - ((h * (h + 1)) / 2));

		int g = ig - (u - (ir - r));

		if(r < h && g < h)
			return 0;

		inode.r = r;
		inode.h = h;

		if(nh.containsKey(inode))
		{
			//System.out.println("Yes");
			return nh.get(inode);
		}

		/*if(dp[r][h] != 0)
		{
			return dp[r][h];
		}*/
		long ans = 0;

		if(h == 1)
		{
			if(r >= 1 && g >= 1)
				ans = 2;
			else
				ans = 1;

			//System.out.println(inode);
			nh.put(inode, (int)ans);

			//dp[r][h] = (int)ans;
			return ans;
		}

		if(r >= h)
		{
			long ans1 = rec(r - h, h - 1);

			ans += ans1;
			ans %= mod;
		}
		if(g >= h)
		{
			long ans2 = rec(r, h - 1);

			ans += ans2;
			ans %= mod;
		}

		//System.out.println(inode);
		nh.put(inode, (int)ans);
		//dp[r][h] = (int)ans;
		return ans;
	}

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

	class InputHelper {
		StringTokenizer tokenizer = null;
		private BufferedReader bufferedReader;

		public InputHelper(InputStream inputStream) {
			InputStreamReader inputStreamReader = new InputStreamReader(
					inputStream);
			bufferedReader = new BufferedReader(inputStreamReader, 16384);
		}

		public String read() {
			while (tokenizer == null || !tokenizer.hasMoreTokens()) {
				try {
					String line = bufferedReader.readLine();
					if (line == null) {
						return null;
					}
					tokenizer = new StringTokenizer(line);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			return tokenizer.nextToken();
		}

		public Integer readInteger() {
			return Integer.parseInt(read());
		}

		public Long readLong() {
			return Long.parseLong(read());
		}
	}
}

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

/*
public class _478D {

}

 */

class node2
{
	int r;
	//int g;
	int h;

	@Override
	public String toString() {
		return "node [r=" + r + ", h=" + h + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + r;
		result = prime * result + h;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		node2 other = (node2) obj;
		if (r != other.r || h != other.h)
			return false;
		return true;
	}
}

public class _478D {
	private static PrintWriter printWriter;

	Map<node2, Integer> nh = new HashMap<node2, Integer>();

	int[][] dp = new int[200001][2];

	int mod = 1000000007;
	int ir = 0, ig = 0, ih = 0, ub = 0;

	public void solve() throws FileNotFoundException {
		InputStream inputStream = System.in;

		InputHelper inputHelper = new InputHelper(inputStream);

		PrintStream out = System.out;

		//actual solution

		int r = inputHelper.readInteger();
		int g = inputHelper.readInteger();

		int h;

		for(h = 1; ; h++)
		{
			if(((h * (h + 1)) / 2) > r + g)
				break;
		}

		h--;

		ub = ((h * (h + 1)) / 2);

		ir = r;
		ig = g;
		ih = h;

		System.out.println(bu());
		//end here

		//printWriter.close();
	}

	private long bu()
	{
		for(int r = 0; r <= ir; r++)
		{
			int u = ub - 1;

			int g = ig - (u - (ir - r));

			if(r >= 1 && g >= 1)
				dp[r][0] = 2;
			else if(r >= 1 || g >= 1)
				dp[r][0] = 1;
			else
				dp[r][0] = 0;
		}

		for(int h = 2; h <= ih; h++)
		{
			for(int r = 0; r <= ir; r++)
			{
				int u = ub - ((h * (h + 1)) / 2);

				int g = ig - (u - (ir - r));

				if(r >= h)
					dp[r][1] = dp[r - h][0];
				if(g >= h)
					dp[r][1] += dp[r][0];
			}

			for(int r = 0; r <= ir; r++)
			{
				dp[r][0] = dp[r][1];
				dp[r][1] = 0;
			}
		}

		return dp[ir][0];
	}

	private long rec(int r, int h)
	{
		if(h < 1)
			return 0;

		int u = (ub - ((h * (h + 1)) / 2));

		int g = ig - (u - (ir - r));

		if(r < h && g < h)
			return 0;

		node2 inode = new node2();

		inode.r = r;
		inode.h = h;

		if(nh.containsKey(inode))
		{
			//System.out.println("Yes");
			return nh.get(inode);
		}

		/*if(dp[r][h] != 0)
		{
			return dp[r][h];
		}*/
		long ans = 0;

		if(h == 1)
		{
			if(r >= 1 && g >= 1)
				ans = 2;
			else
				ans = 1;

			//System.out.println(inode);
			nh.put(inode, (int)ans);

			dp[r][h] = 1;//(int)ans;
			return ans;
		}

		if(r >= h)
		{
			long ans1 = rec(r - h, h - 1);

			ans += ans1;
			ans %= mod;
		}
		if(g >= h)
		{
			long ans2 = rec(r, h - 1);

			ans += ans2;
			ans %= mod;
		}

		//System.out.println(inode);
		nh.put(inode, (int)ans);
		dp[r][h] = 1;//(int)ans;
		return ans;
	}

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

	class InputHelper {
		StringTokenizer tokenizer = null;
		private BufferedReader bufferedReader;

		public InputHelper(InputStream inputStream) {
			InputStreamReader inputStreamReader = new InputStreamReader(
					inputStream);
			bufferedReader = new BufferedReader(inputStreamReader, 16384);
		}

		public String read() {
			while (tokenizer == null || !tokenizer.hasMoreTokens()) {
				try {
					String line = bufferedReader.readLine();
					if (line == null) {
						return null;
					}
					tokenizer = new StringTokenizer(line);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			return tokenizer.nextToken();
		}

		public Integer readInteger() {
			return Integer.parseInt(read());
		}

		public Long readLong() {
			return Long.parseLong(read());
		}
	}
}

/**
 * Created by Aminul on 12/19/2017.
 */

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

import static java.lang.Math.max;

public class CF478D_3 {
    static int R, G, dp[][], MAX_H, mod = (int)1e9+7;
    public static void main(String[] args) throws Exception {
        FastReader in = new FastReader(System.in);
        PrintWriter pw = new PrintWriter(System.out);

        R = in.nextInt(); G = in.nextInt();

        pw.println(solve());

        pw.close();
    }
    static int solve(){
        dp = new int[2][R+1];
        dp[0][0] = 1;
        int cur = 1, ways = 0;
        for(int i = 1; i < 920; i++){

            for(int j = 0; j <= R; j++){
                if(dp[cur ^ 1][j] == 0) continue;

                int h = i-1;
                int total = (h*(h+1))/2; // already total used balls
                h++; // current h
                int r = R - j; // remaining R
                int g = G - ( total - (R - r) ) ; // remaining G

                if(g >= h) dp[cur][j] = (dp[cur][j] + dp[cur ^ 1][j]) % mod;
                if(r >= h && j+h <= R) dp[cur][j+h] = (dp[cur][j+h] + dp[cur ^ 1][j] ) % mod;

            }

            int temp = 0;
            for(int j = 0; j <= R; j++){
                temp = (temp + dp[cur][j]) % mod;
                dp[cur^1][j] = 0;  // resetting for next iteration
            }
            if(temp > 0 && i > 1) ways = temp;

            cur ^= 1;

        }

        return ways;

    }

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

    static class FastReader {
        InputStream is;
        private byte[] inbuf = new byte[1024];
        private int lenbuf = 0, ptrbuf = 0;
        static final int ints[] = new int[128];

        public FastReader(InputStream is) {
            for (int i = '0'; i <= '9'; i++) ints[i] = i - '0';
            this.is = is;
        }

        public 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++];
        }

        public boolean isSpaceChar(int c) {
            return !(c >= 33 && c <= 126);
        }

        public int skip() {
            int b;
            while ((b = readByte()) != -1 && isSpaceChar(b)) ;
            return b;
        }

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

        public int nextInt() {
            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 << 3) + (num << 1) + ints[b];
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        public long nextLong() {
            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 << 3) + (num << 1) + ints[b];
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }
       /* public char nextChar() {
            return (char)skip();
        }*/

        public char[] next(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 buff[] = new char[1005];
        public char[] nextCharArray(){
            int b = skip(), p = 0;
            while(!(isSpaceChar(b))){
                buff[p++] = (char)b;
                b = readByte();
            }
            return Arrays.copyOf(buff, p);
        }*/
    }
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class RedGreenTowers {
	static int r, g, h, parity, total;
	static int[][] dp = new int[200001][2];
	static int mod = (int) 1e9 + 7;

	static long findh() {
		long max = 0;
		long lo = 1;
		long hi = Math.max(r, g);

		while (lo <= hi) {
			long mid = lo + (hi - lo) / 2;
			if (mid * (mid + 1) / 2 <= r + g) {
				max = Math.max(max, mid);
				lo = mid + 1;
			} else
				hi = mid - 1;
		}

		return max;
	}

	public static void dp() {
		for (int i = 0; i <= r; i++)
			dp[i][0] = 1;

		parity = 1;

		for (int lvl = 1; lvl <= h; lvl++) {
			int used = total - (lvl * (lvl + 1) / 2);

			for (int remr = 0; remr <= r; remr++) {
				int usedr = r - remr;
				int usedg = used - usedr;
				int remg = g - usedg;

				if (remg < 0)
					continue;

				int val1 = 0;
				int val2 = 0;

				if (remr >= lvl)
					val1 = dp[remr - lvl][parity ^ 1] % mod;

				if (remg >= lvl)
					val2 = dp[remr][parity ^ 1] % mod;

				dp[remr][parity] = val1 + val2;
			}
			parity ^= 1;
		}
	}

	public static void main(String[] args) throws IOException {
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(bf.readLine());
		r = Integer.parseInt(st.nextToken());
		g = Integer.parseInt(st.nextToken());
		h = (int) findh();
		total = h * (h + 1) / 2;
		dp();
		System.out.println(dp[r][parity ^ 1]);

	}
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class RedGreenTowers {
	static int r, g, h;
	static int[][] memo;
	static int mod = (int) 1e9 + 7;

	static int findh() {
		int max = 0;
		int lo = 1;
		int hi = Math.max(r, g);

		while (lo <= hi) {
			int mid = (lo + hi) / 2;
			if (mid * (mid + 1) / 2 <= r + g) {
				max = Math.max(max, mid);
				lo = mid + 1;
			} else
				hi = mid - 1;
		}

		return max;
	}

	static int dp(int remr, int remg, int curlvl) {
		if (curlvl == 0)
			return 1;

		if (memo[remr][remg] != -1)
			return memo[remr][remg];

		int red = 0;
		int green = 0;

		if (remr >= curlvl)
			red = dp(remr - curlvl, remg, curlvl - 1) % mod;

		if (remg >= curlvl)
			green = dp(remr, remg - curlvl, curlvl - 1) % mod;

		return memo[remr][remg] = red + green;
	}

	public static void main(String[] args) throws IOException {
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(bf.readLine());
		r = Integer.parseInt(st.nextToken());
		g = Integer.parseInt(st.nextToken());
		h = findh();
		memo = new int[r + 1][g + 1];
		for (int i = 0; i <= r; i++)
			Arrays.fill(memo[i], -1);
	   // System.out.println(h);
		System.out.println(dp(r, g, h));

	}
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class RedGreenTowers {
	static int r, g, h;
	static int[][] memo;
	static int mod = (int) 1e9 + 7;

	static int findh() {
		int max = 0;
		int lo = 1;
		int hi = Math.max(r, g);

		while (lo <= hi) {
			int mid = (lo + hi) / 2;
			if (mid * (mid + 1) / 2 <= r + g) {
				max = Math.max(max, mid);
				lo = mid + 1;
			} else
				hi = mid - 1;
		}

		return max;
	}

	static int dp(int remr, int remg, int curlvl) {
		if (curlvl == 0)
			return 1;

		if (memo[remr][remg] != -1)
			return memo[remr][remg];

		int red = 0;
		int green = 0;

		if (remr >= curlvl)
			red = dp(remr - curlvl, remg, curlvl - 1) % mod;

		if (remg >= curlvl)
			green = dp(remr, remg - curlvl, curlvl - 1) % mod;

		return memo[remr][remg] = red + green;
	}

	public static void main(String[] args) throws IOException {
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(bf.readLine());
		r = Integer.parseInt(st.nextToken());
		g = Integer.parseInt(st.nextToken());
		h = findh();
		memo = new int[r + 1][g + 1];
		for (int i = 0; i <= r; i++)
			Arrays.fill(memo[i], -1);
	    System.out.println(h);
		System.out.println(dp(r, g, h));

	}
}

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

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

    static class DRedGreenTowers {
        public void solve(int testNumber, inputClass sc, PrintWriter out) {
            int r = sc.nextInt();
            int g = sc.nextInt();
            if (g > r) {
                int tmp = g;
                g = r;
                r = tmp;
            }
            int h = 1;
            while ((long) h * (h + 1) / 2 <= r + g) {
                h++;
            }
            h--;
            long[][] dp = new long[h][r + 1];
            boolean[][] go = new boolean[h][r + 1];
            dp[0][0] = 1;
            go[0][0] = true;
            if (g > 0) {
                dp[0][1] = 1;
                go[0][1] = true;
            }
            int mod = (int) 1e9 + 7;
            for (int i = 0; i < h - 1; i++) {
                for (int j = 0; j < r + 1; j++) {
                    if (go[i][j]) {
                        int usedg = (i + 2) * (i + 1) / 2 - j;
                        if (j + (i + 1) + 1 <= r) {
                            dp[i + 1][j + i + 1] += dp[i][j];
                            dp[i + 1][j + i + 1] %= mod;
                            go[i + 1][j + i + 1] = true;
                        }
                        if (usedg + (i + 1) + 1 <= g) {
                            dp[i + 1][j] += dp[i][j];
                            dp[i + 1][j] %= mod;
                            go[i + 1][j] = true;
                        }
                    }
                }
            }
            long ans = 0;
            for (int i = 0; i < r + 1; i++) {
                ans += dp[h - 1][i];
                ans %= mod;
            }
            out.println(ans);

        }

    }

    static class inputClass {
        BufferedReader br;
        StringTokenizer st;

        public inputClass(InputStream in) {

            br = new BufferedReader(new InputStreamReader(in));
        }

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

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

    }
}

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

public class icpc
{
    public static final int M = (int)(1e9 + 7);
    public static void main(String[] args) throws IOException
    {
        Reader in = new Reader();
        //BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        int r = in.nextInt();
        int g = in.nextInt();
        int h = 0;
        for (int i=1;i<=1000;i++)
            if ((i * (i + 1)) / 2 > r + g)
            {
                h = i - 1;
                break;
            }

        long[] dp = new long[r + 1];
        dp[0] = 1;
        for (int i=1;i<=h;i++)
        {
            for (int j=r - i;j>=0;j--)
            {
                dp[j + i] += dp[j];
                dp[j + i] %= M;
            }
        }
        int ans = 0;
        for (int i=0;i<=r;i++)
            if (h * (h + 1) / 2 - i <= g)
                ans += dp[i];
        System.out.println(ans % M);
    }
}
class DSU
{
    int[] parent;
    int[] size;
    //Pass number of total nodes as parameter to the constructor
    DSU(int n)
    {
        this.parent = new int[n];
        this.size = new int[n];
        Arrays.fill(parent, -1);
    }

    public void makeSet(int v)
    {
        parent[v] = v;
        size[v] = 1;
    }

    public int findSet(int v)
    {
        if (v == parent[v]) return v;
        return parent[v] = findSet(parent[v]);
    }

    public void unionSets(int a, int b)
    {
        a = findSet(a);
        b = findSet(b);
        if (a != b)
        {
            if (size[a] < size[b])
            {
                int temp = a;
                a = b;
                b = temp;
            }
            parent[b] = a;
            size[a] += size[b];
        }
    }
}
class FastFourierTransform
{
    private void fft(double[] a, double[] b, boolean invert)
    {
        int count = a.length;
        for (int i = 1, j = 0; i < count; i++)
        {
            int bit = count >> 1;
            for (; j >= bit; bit >>= 1)
                j -= bit;
            j += bit;
            if (i < j)
            {
                double temp = a[i];
                a[i] = a[j];
                a[j] = temp;
                temp = b[i];
                b[i] = b[j];
                b[j] = temp;
            }
        }
        for (int len = 2; len <= count; len <<= 1)
        {
            int halfLen = len >> 1;
            double angle = 2 * Math.PI / len;
            if (invert)
                angle = -angle;
            double wLenA = Math.cos(angle);
            double wLenB = Math.sin(angle);
            for (int i = 0; i < count; i += len)
            {
                double wA = 1;
                double wB = 0;
                for (int j = 0; j < halfLen; j++)
                {
                    double uA = a[i + j];
                    double uB = b[i + j];
                    double vA = a[i + j + halfLen] * wA - b[i + j + halfLen] * wB;
                    double vB = a[i + j + halfLen] * wB + b[i + j + halfLen] * wA;
                    a[i + j] = uA + vA;
                    b[i + j] = uB + vB;
                    a[i + j + halfLen] = uA - vA;
                    b[i + j + halfLen] = uB - vB;
                    double nextWA = wA * wLenA - wB * wLenB;
                    wB = wA * wLenB + wB * wLenA;
                    wA = nextWA;
                }
            }
        }
        if (invert)
        {
            for (int i = 0; i < count; i++)
            {
                a[i] /= count;
                b[i] /= count;
            }
        }
    }

    public long[] multiply(long[] a, long[] b)
    {
        int resultSize = Integer.highestOneBit(Math.max(a.length, b.length) - 1) << 2;
        resultSize = Math.max(resultSize, 1);
        double[] aReal = new double[resultSize];
        double[] aImaginary = new double[resultSize];
        double[] bReal = new double[resultSize];
        double[] bImaginary = new double[resultSize];
        for (int i = 0; i < a.length; i++)
            aReal[i] = a[i];
        for (int i = 0; i < b.length; i++)
            bReal[i] = b[i];
        fft(aReal, aImaginary, false);
        fft(bReal, bImaginary, false);
        for (int i = 0; i < resultSize; i++)
        {
            double real = aReal[i] * bReal[i] - aImaginary[i] * bImaginary[i];
            aImaginary[i] = aImaginary[i] * bReal[i] + bImaginary[i] * aReal[i];
            aReal[i] = real;
        }
        fft(aReal, aImaginary, true);
        long[] result = new long[resultSize];
        for (int i = 0; i < resultSize; i++)
            result[i] = Math.round(aReal[i]);
        return result;
    }
}
class NumberTheory
{
    public boolean isPrime(long n)
    {
        if(n < 2)
            return false;
        for(long x = 2;x * x <= n;x++)
        {
            if(n % x == 0)
                return false;
        }
        return true;
    }
    public ArrayList<Long> primeFactorisation(long n)
    {
        ArrayList<Long> f = new ArrayList<>();
        for(long x=2;x * x <= n;x++)
        {
            while(n % x == 0)
            {
                f.add(x);
                n /= x;
            }
        }
        if(n > 1)
            f.add(n);
        return f;
    }
    public int[] sieveOfEratosthenes(int n)
    {
        //Returns an array with the smallest prime factor for each number and primes marked as 0
        int[] sieve = new int[n + 1];
        for(int x=2;x * x <= n;x++)
        {
            if(sieve[x] != 0)
                continue;
            for(int u=x*x;u<=n;u+=x)
            {
                if(sieve[u] == 0)
                {
                    sieve[u] = x;
                }
            }
        }
        return sieve;
    }
    public long gcd(long a, long b)
    {
        if(b == 0)
            return a;
        return gcd(b, a % b);
    }
    public long phi(long n)
    {
        double result = n;

        for(long p=2;p*p<=n;p++)
        {
            if(n % p == 0)
            {
                while (n % p == 0)
                    n /= p;
                result *= (1.0 - (1.0 / (double)p));
            }
        }
        if(n > 1)
            result *= (1.0 - (1.0 / (double)n));
        return (long)result;
    }
    public Name extendedEuclid(long a, long b)
    {
        if(b == 0)
            return new Name(a, 1, 0);
        Name n1 = extendedEuclid(b, a % b);
        Name n2 = new Name(n1.d, n1.y, n1.x - (long)Math.floor((double)a / b) * n1.y);
        return n2;
    }
    public long modularExponentiation(long a, long b, long n)
    {
        long d = 1L;
        String bString = Long.toBinaryString(b);
        for(int i=0;i<bString.length();i++)
        {
            d = (d * d) % n;
            if(bString.charAt(i) == '1')
                d = (d * a) % n;
        }
        return d;
    }
}
class Name
{
    long d;
    long x;
    long y;

    public Name(long d, long x, long y)
    {
        this.d = d;
        this.x = x;
        this.y = y;
    }
}
class SuffixArray
{
    int ALPHABET_SZ = 256, N;
    int[] T, lcp, sa, sa2, rank, tmp, c;

    public SuffixArray(String str)
    {
        this(toIntArray(str));
    }

    private static int[] toIntArray(String s)
    {
        int[] text = new int[s.length()];
        for (int i = 0; i < s.length(); i++) text[i] = s.charAt(i);
        return text;
    }

    public SuffixArray(int[] text)
    {
        T = text;
        N = text.length;
        sa = new int[N];
        sa2 = new int[N];
        rank = new int[N];
        c = new int[Math.max(ALPHABET_SZ, N)];
        construct();
        kasai();
    }

    private void construct()
    {
        int i, p, r;
        for (i = 0; i < N; ++i) c[rank[i] = T[i]]++;
        for (i = 1; i < ALPHABET_SZ; ++i) c[i] += c[i - 1];
        for (i = N - 1; i >= 0; --i) sa[--c[T[i]]] = i;
        for (p = 1; p < N; p <<= 1)
        {
            for (r = 0, i = N - p; i < N; ++i) sa2[r++] = i;
            for (i = 0; i < N; ++i) if (sa[i] >= p) sa2[r++] = sa[i] - p;
            Arrays.fill(c, 0, ALPHABET_SZ, 0);
            for (i = 0; i < N; ++i) c[rank[i]]++;
            for (i = 1; i < ALPHABET_SZ; ++i) c[i] += c[i - 1];
            for (i = N - 1; i >= 0; --i) sa[--c[rank[sa2[i]]]] = sa2[i];
            for (sa2[sa[0]] = r = 0, i = 1; i < N; ++i)
            {
                if (!(rank[sa[i - 1]] == rank[sa[i]]
                        && sa[i - 1] + p < N
                        && sa[i] + p < N
                        && rank[sa[i - 1] + p] == rank[sa[i] + p])) r++;
                sa2[sa[i]] = r;
            }
            tmp = rank;
            rank = sa2;
            sa2 = tmp;
            if (r == N - 1) break;
            ALPHABET_SZ = r + 1;
        }
    }

    private void kasai()
    {
        lcp = new int[N];
        int[] inv = new int[N];
        for (int i = 0; i < N; i++) inv[sa[i]] = i;
        for (int i = 0, len = 0; i < N; i++)
        {
            if (inv[i] > 0)
            {
                int k = sa[inv[i] - 1];
                while ((i + len < N) && (k + len < N) && T[i + len] == T[k + len]) len++;
                lcp[inv[i] - 1] = len;
                if (len > 0) len--;
            }
        }
    }
}
class ZAlgorithm
{
    public int[] calculateZ(char input[])
    {
        int Z[] = new int[input.length];
        int left = 0;
        int right = 0;
        for(int k = 1; k < input.length; k++) {
            if(k > right) {
                left = right = k;
                while(right < input.length && input[right] == input[right - left]) {
                    right++;
                }
                Z[k] = right - left;
                right--;
            } else {
                //we are operating inside box
                int k1 = k - left;
                //if value does not stretches till right bound then just copy it.
                if(Z[k1] < right - k + 1) {
                    Z[k] = Z[k1];
                } else { //otherwise try to see if there are more matches.
                    left = k;
                    while(right < input.length && input[right] == input[right - left]) {
                        right++;
                    }
                    Z[k] = right - left;
                    right--;
                }
            }
        }
        return Z;
    }
    public ArrayList<Integer> matchPattern(char text[], char pattern[])
    {
        char newString[] = new char[text.length + pattern.length + 1];
        int i = 0;
        for(char ch : pattern) {
            newString[i] = ch;
            i++;
        }
        newString[i] = '$';
        i++;
        for(char ch : text) {
            newString[i] = ch;
            i++;
        }
        ArrayList<Integer> result = new ArrayList<>();
        int Z[] = calculateZ(newString);

        for(i = 0; i < Z.length ; i++) {
            if(Z[i] == pattern.length) {
                result.add(i - pattern.length - 1);
            }
        }
        return result;
    }
}
class KMPAlgorithm
{
    public int[] computeTemporalArray(char[] pattern)
    {
        int[] lps = new int[pattern.length];

        int index = 0;
        for(int i=1;i<pattern.length;)
        {
            if(pattern[i] == pattern[index])
            {
                lps[i] = index + 1;
                index++;
                i++;
            }
            else
            {
                if(index != 0)
                {
                    index = lps[index - 1];
                }
                else
                {
                    lps[i] = 0;
                    i++;
                }
            }
        }
        return lps;
    }

    public ArrayList<Integer> KMPMatcher(char[] text, char[] pattern)
    {
        int[] lps = computeTemporalArray(pattern);

        int j = 0;
        int i = 0;
        int n = text.length;
        int m = pattern.length;
        ArrayList<Integer> indices = new ArrayList<>();
        while(i < n)
        {
            if(pattern[j] == text[i])
            {
                i++;
                j++;
            }
            if(j == m)
            {
                indices.add(i - j);
                j = lps[j - 1];
            }
            else if(i < n && pattern[j] != text[i])
            {
                if(j != 0)
                    j = lps[j - 1];
                else
                    i = i + 1;
            }
        }
        return indices;
    }
}
class Hashing
{
    public long[] computePowers(long p, int n, long m)
    {
        long[] powers = new long[n];
        powers[0] = 1;
        for(int i=1;i<n;i++)
        {
            powers[i] = (powers[i - 1] * p) % m;
        }
        return powers;
    }
    public long computeHash(String s)
    {
        long p = 31;
        long m = 1_000_000_009;
        long hashValue = 0L;
        long[] powers = computePowers(p, s.length(), m);
        for(int i=0;i<s.length();i++)
        {
            char ch = s.charAt(i);
            hashValue = (hashValue + (ch - 'a' + 1) * powers[i]) % m;
        }
        return hashValue;
    }
}
class BasicFunctions
{
    public int maxOfIntArray(int[] A)
    {
        int max = Integer.MIN_VALUE;
        for (int i=0;i<A.length;i++)    max = Math.max(max, A[i]);
        return max;
    }
    public long maxOfLongArray(long[] A)
    {
        long max = Long.MIN_VALUE;
        for (int i=0;i<A.length;i++)    max = Math.max(max, A[i]);
        return max;
    }
    public int minOfIntArray(int[] A)
    {
        int min = Integer.MAX_VALUE;
        for (int i=0;i<A.length;i++)    min = Math.min(min, A[i]);
        return min;
    }
    public long minOfLongArray(long[] A)
    {
        long min = Long.MAX_VALUE;
        for (int i=0;i<A.length;i++)    min = Math.min(min, A[i]);
        return min;
    }

}
class MergeSortInt
{
    // Merges two subarrays of arr[].
    // First subarray is arr[l..m]
    // Second subarray is arr[m+1..r]
    void merge(int arr[], int l, int m, int r) {
        // Find sizes of two subarrays to be merged
        int n1 = m - l + 1;
        int n2 = r - m;

        /* Create temp arrays */
        int L[] = new int[n1];
        int R[] = new int[n2];

        /*Copy data to temp arrays*/
        for (int i = 0; i < n1; ++i)
            L[i] = arr[l + i];
        for (int j = 0; j < n2; ++j)
            R[j] = arr[m + 1 + j];

        /* Merge the temp arrays */

        // Initial indexes of first and second subarrays
        int i = 0, j = 0;

        // Initial index of merged subarry array
        int k = l;
        while (i < n1 && j < n2) {
            if (L[i] <= R[j]) {
                arr[k] = L[i];
                i++;
            } else {
                arr[k] = R[j];
                j++;
            }
            k++;
        }

        /* Copy remaining elements of L[] if any */
        while (i < n1) {
            arr[k] = L[i];
            i++;
            k++;
        }

        /* Copy remaining elements of R[] if any */
        while (j < n2) {
            arr[k] = R[j];
            j++;
            k++;
        }
    }

    // Main function that sorts arr[l..r] using
    // merge()
    void sort(int arr[], int l, int r) {
        if (l < r) {
            // Find the middle point
            int m = (l + r) / 2;

            // Sort first and second halves
            sort(arr, l, m);
            sort(arr, m + 1, r);

            // Merge the sorted halves
            merge(arr, l, m, r);
        }
    }

}
class MergeSortLong
{
    // Merges two subarrays of arr[].
    // First subarray is arr[l..m]
    // Second subarray is arr[m+1..r]
    void merge(long arr[], int l, int m, int r) {
        // Find sizes of two subarrays to be merged
        int n1 = m - l + 1;
        int n2 = r - m;

        /* Create temp arrays */
        long L[] = new long[n1];
        long R[] = new long[n2];

        /*Copy data to temp arrays*/
        for (int i = 0; i < n1; ++i)
            L[i] = arr[l + i];
        for (int j = 0; j < n2; ++j)
            R[j] = arr[m + 1 + j];

        /* Merge the temp arrays */

        // Initial indexes of first and second subarrays
        int i = 0, j = 0;

        // Initial index of merged subarry array
        int k = l;
        while (i < n1 && j < n2) {
            if (L[i] <= R[j]) {
                arr[k] = L[i];
                i++;
            } else {
                arr[k] = R[j];
                j++;
            }
            k++;
        }

        /* Copy remaining elements of L[] if any */
        while (i < n1) {
            arr[k] = L[i];
            i++;
            k++;
        }

        /* Copy remaining elements of R[] if any */
        while (j < n2) {
            arr[k] = R[j];
            j++;
            k++;
        }
    }

    // Main function that sorts arr[l..r] using
    // merge()
    void sort(long arr[], int l, int r) {
        if (l < r) {
            // Find the middle point
            int m = (l + r) / 2;

            // Sort first and second halves
            sort(arr, l, m);
            sort(arr, m + 1, r);

            // Merge the sorted halves
            merge(arr, l, m, r);
        }
    }
}
class Node
{

    int x;
    int y;

    public Node(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(Object ob)
    {
        if(ob == null)
            return false;
        if(!(ob instanceof Node))
            return false;
        if(ob == this)
            return true;
        Node obj = (Node)ob;
        if(this.x == obj.x && this.y == obj.y)
            return true;
        return false;
    }

    @Override
    public int hashCode()
    {
        return (int)this.x;
    }
}
class Reader
{
    final private int BUFFER_SIZE = 1 << 16;
    private DataInputStream din;
    private byte[] buffer;
    private int bufferPointer, bytesRead;

    public Reader()
    {
        din = new DataInputStream(System.in);
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public Reader(String file_name) throws IOException
    {
        din = new DataInputStream(new FileInputStream(file_name));
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public String readLine() throws IOException
    {
        byte[] buf = new byte[64]; // line length
        int cnt = 0, c;
        while ((c = read()) != -1)
        {
            if (c == '\n')
                break;
            buf[cnt++] = (byte) c;
        }
        return new String(buf, 0, cnt);
    }

    public int nextInt() throws IOException
    {
        int ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do
        {
            ret = ret * 10 + c - '0';
        }  while ((c = read()) >= '0' && c <= '9');

        if (neg)
            return -ret;
        return ret;
    }

    public long nextLong() throws IOException
    {
        long ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');
        if (neg)
            return -ret;
        return ret;
    }

    public double nextDouble() throws IOException
    {
        double ret = 0, div = 1;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();

        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');

        if (c == '.')
        {
            while ((c = read()) >= '0' && c <= '9')
            {
                ret += (c - '0') / (div *= 10);
            }
        }

        if (neg)
            return -ret;
        return ret;
    }

    private void fillBuffer() throws IOException
    {
        bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
        if (bytesRead == -1)
            buffer[0] = -1;
    }

    private byte read() throws IOException
    {
        if (bufferPointer == bytesRead)
            fillBuffer();
        return buffer[bufferPointer++];
    }

    public void close() throws IOException
    {
        if (din == null)
            return;
        din.close();
    }
}
class SegmentTree
{
    public int nextPowerOfTwo(int num)
    {
        if(num == 0)
            return 1;
        if(num > 0 && (num & (num - 1)) == 0)
            return num;
        while((num &(num - 1)) > 0)
        {
            num = num & (num - 1);
        }
        return num << 1;
    }
    public int[] createSegmentTree(int[] input)
    {
        int np2 = nextPowerOfTwo(input.length);
        int[] segmentTree = new int[np2 * 2 - 1];

        for(int i=0;i<segmentTree.length;i++)
            segmentTree[i] = Integer.MIN_VALUE;

        constructSegmentTree(segmentTree,input,0,input.length-1,0);
        return segmentTree;

    }
    private void constructSegmentTree(int[] segmentTree,int[] input,int low,int high,int pos)
    {
        if(low == high)
        {
            segmentTree[pos] = input[low];
            return;
        }
        int mid = (low + high)/ 2;
        constructSegmentTree(segmentTree,input,low,mid,2*pos + 1);
        constructSegmentTree(segmentTree,input,mid+1,high,2*pos + 2);
        segmentTree[pos] = Math.max(segmentTree[2*pos + 1],segmentTree[2*pos + 2]);
    }
    public int rangeMinimumQuery(int []segmentTree,int qlow,int qhigh,int len)
    {
        return rangeMinimumQuery(segmentTree,0,len-1,qlow,qhigh,0);
    }
    private int rangeMinimumQuery(int segmentTree[],int low,int high,int qlow,int qhigh,int pos)
    {
        if(qlow <= low && qhigh >= high){
            return segmentTree[pos];
        }
        if(qlow > high || qhigh < low){
            return Integer.MIN_VALUE;
        }
        int mid = (low+high)/2;
        return Math.max(rangeMinimumQuery(segmentTree, low, mid, qlow, qhigh, 2 * pos + 1),
                rangeMinimumQuery(segmentTree, mid + 1, high, qlow, qhigh, 2 * pos + 2));
    }
}
class Trie
{

    private class TrieNode
    {
        Map<Character, TrieNode> children;
        boolean endOfWord;
        public TrieNode()
        {
            children = new HashMap<>();
            endOfWord = false;
        }
    }

    private final TrieNode root;
    public Trie()
    {
        root = new TrieNode();
    }

    public void insert(String word)
    {
        TrieNode current = root;
        for (int i = 0; i < word.length(); i++)
        {
            char ch = word.charAt(i);
            TrieNode node = current.children.get(ch);
            if (node == null)
            {
                node = new TrieNode();
                current.children.put(ch, node);
            }
            current = node;
        }
        current.endOfWord = true;
    }

    public boolean search(String word)
    {
        TrieNode current = root;
        for (int i = 0; i < word.length(); i++)
        {
            char ch = word.charAt(i);
            TrieNode node = current.children.get(ch);
            if (node == null)
            {
                return false;
            }
            current = node;
        }
        return current.endOfWord;
    }

    public void delete(String word)
    {
        delete(root, word, 0);
    }

    private boolean delete(TrieNode current, String word, int index)
    {
        if (index == word.length())
        {
            if (!current.endOfWord)
            {
                return false;
            }
            current.endOfWord = false;
            return current.children.size() == 0;
        }
        char ch = word.charAt(index);
        TrieNode node = current.children.get(ch);
        if (node == null)
        {
            return false;
        }
        boolean shouldDeleteCurrentNode = delete(node, word, index + 1);

        if (shouldDeleteCurrentNode)
        {
            current.children.remove(ch);
            return current.children.size() == 0;
        }
        return false;
    }
}
class SegmentTreeLazy
{
    public int nextPowerOfTwo(int num)
    {
        if(num == 0)
            return 1;
        if(num > 0 && (num & (num - 1)) == 0)
            return num;
        while((num &(num - 1)) > 0)
        {
            num = num & (num - 1);
        }
        return num << 1;
    }

    public int[] createSegmentTree(int input[])
    {
        int nextPowOfTwo = nextPowerOfTwo(input.length);
        int segmentTree[] = new int[nextPowOfTwo*2 -1];

        for(int i=0; i < segmentTree.length; i++){
            segmentTree[i] = Integer.MAX_VALUE;
        }
        constructMinSegmentTree(segmentTree, input, 0, input.length - 1, 0);
        return segmentTree;
    }

    private void constructMinSegmentTree(int segmentTree[], int input[], int low, int high,int pos)
    {
        if(low == high)
        {
            segmentTree[pos] = input[low];
            return;
        }
        int mid = (low + high)/2;
        constructMinSegmentTree(segmentTree, input, low, mid, 2 * pos + 1);
        constructMinSegmentTree(segmentTree, input, mid + 1, high, 2 * pos + 2);
        segmentTree[pos] = Math.min(segmentTree[2*pos+1], segmentTree[2*pos+2]);
    }

    public void updateSegmentTreeRangeLazy(int input[], int segmentTree[], int lazy[], int startRange, int endRange, int delta)
    {
        updateSegmentTreeRangeLazy(segmentTree, lazy, startRange, endRange, delta, 0, input.length - 1, 0);
    }

    private void updateSegmentTreeRangeLazy(int segmentTree[], int lazy[], int startRange, int endRange, int delta, int low, int high, int pos)
    {
        if(low > high)
        {
            return;
        }
        if (lazy[pos] != 0)
        {
            segmentTree[pos] += lazy[pos];
            if (low != high)
            {
                lazy[2 * pos + 1] += lazy[pos];
                lazy[2 * pos + 2] += lazy[pos];
            }
            lazy[pos] = 0;
        }

        if(startRange > high || endRange < low)
        {
            return;
        }

        if(startRange <= low && endRange >= high)
        {
            segmentTree[pos] += delta;
            if(low != high) {
                lazy[2*pos + 1] += delta;
                lazy[2*pos + 2] += delta;
            }
            lazy[pos] = 0;
        }

        int mid = (low + high)/2;
        updateSegmentTreeRangeLazy(segmentTree, lazy, startRange, endRange, delta, low, mid, 2*pos+1);
        updateSegmentTreeRangeLazy(segmentTree, lazy, startRange, endRange, delta, mid+1, high, 2*pos+2);
        segmentTree[pos] = Math.min(segmentTree[2*pos + 1], segmentTree[2*pos + 2]);
    }

    public int rangeMinimumQueryLazy(int segmentTree[], int lazy[], int qlow, int qhigh, int len)
    {
        return rangeMinimumQueryLazy(segmentTree, lazy, qlow, qhigh, 0, len - 1, 0);
    }

    private int rangeMinimumQueryLazy(int segmentTree[], int lazy[], int qlow, int qhigh, int low, int high, int pos)
    {
        if(low > high)
        {
            return Integer.MAX_VALUE;
        }
        if (lazy[pos] != 0)
        {
            segmentTree[pos] += lazy[pos];
            if (low != high)
            {
                lazy[2 * pos + 1] += lazy[pos];
                lazy[2 * pos + 2] += lazy[pos];
            }
            lazy[pos] = 0;
        }

        if(qlow > high || qhigh < low)
        {
            return Integer.MAX_VALUE;
        }

        if(qlow <= low && qhigh >= high)
        {
            return segmentTree[pos];
        }

        int mid = (low+high)/2;
        return Math.min(rangeMinimumQueryLazy(segmentTree, lazy, qlow, qhigh, low, mid, 2 * pos + 1), rangeMinimumQueryLazy(segmentTree, lazy,  qlow, qhigh, mid + 1, high, 2 * pos + 2));
    }
}
class BIT
{
    int size;
    int[] table;
    public BIT(int size)
    {
        table = new int[size];
        this.size = size;
    }

    void update(int i, long delta)
    {
        while (i < size)
        {
            table[i] += delta;
            i += Integer.lowestOneBit(i);
        }
    }

    int sum(int i)
    {
        int sum = 0;
        while (i > 0)
        {
            sum += table[i];
            i -= Integer.lowestOneBit(i);
        }
        return sum;
    }
}

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

public class Abc {
    static int r,g;
    static long dp[][];
    static int h=1;
    static int mod=1000000007;
    public static void main(String[] args) {
        FastReader sc = new FastReader();
        r=sc.nextInt();g=sc.nextInt();
        int x=g+r;
        int y=0;
        while (true){
            y+=h;
            if (y+h+1>x)break;
            h++;
        }
        dp=new long[2][r+1];
        if (r>=1)dp[1][r-1]=1;
        if (g>=1)dp[1][r]=1;
        int p=0;
        for (int i=2;i<=h;i++){
            Arrays.fill(dp[p],0);
            for (int j=0;j<=r;j++){
                int gr=g-(i*(i-1)/2)+r-j;
                if (gr>g)continue;
                if (gr>=i)dp[p][j]=dp[p^1][j];
                if (j>=i)dp[p][j-i]+=dp[p^1][j];
            }
            p=(p^1);
        }
        long ans=0;
        for (int i=0;i<=r;i++){
            ans=(ans+dp[p^1][i])%mod;
        }
        System.out.println(ans);
    }
    static long dp(int i,int rr){
//        System.out.println(i+" "+rr);
        int gr=g-((i-1)*(i)/2 - (r-rr));
        if (i==h){
            if (gr>=i && rr>=i)return 2;
            else if (gr>=i || rr>=i)return 1;
        }
//        System.out.println(i+" "+rr+" "+gr);
        if (i>rr && gr<i )return 0;
        if (dp[i][rr]!=-1)return dp[i][rr]%mod;
//        System.out.println(i+" "+rr);
        if (gr>=i && rr>=i){
//            System.out.println(i+" "+rr);
            dp[i][rr]=(dp(i+1,rr)%mod+dp(i+1,rr-i)%mod)%mod;
        }else if (gr<i)dp[i][rr]=dp(i+1,rr-i)%mod;
        else dp[i][rr]=dp(i+1,rr)%mod;
        return dp[i][rr];
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

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

        String next() {
            while (st == null || !st.hasMoreElements()) {
                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());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

import java.awt.Point;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Currency;
import java.util.HashSet;
import java.util.List;
import java.util.SortedSet;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.TreeSet;

/**
 * @author Jens Staahl
 */

public class Prac {

	// some local config
	// static boolean test = false ;
	private boolean test = System.getProperty("ONLINE_JUDGE") == null;
	static String testDataFile = "testdata.txt";
	// static String testDataFile = "testdata.txt";
	private static String ENDL = "\n";
	// Just solves the acutal kattis-problem
	ZKattio io;
	private void solve() throws Throwable {
		io = new ZKattio(stream);
		int g = io.getInt(), r = io.getInt();
		int h = 0;
		int sum = g + r;

		while(sum > 0) {
			h ++;
			sum -= h;
		}
		if(sum < 0 ) {
			h --;
		}
		long[] dp = new long[r+1];
		dp[0] = 1;
		for (int layer = 1; layer <= h ; layer++) {
			for (int used = r; used >= 0; used--) {
				if(r - used > 0 && used + layer <= r) {
					dp[used+layer] += dp[used];
				}
			}
		}
		long ans = 0;
		final int mod = 1000000007;
		int cnt = h * (h+1)/2;
		for (int i = 0; i < dp.length; i++) {
			if(i + g >= cnt) {
				ans += dp[i];
				if(ans > mod) {
					ans -= mod;
				}
			}
		}

		System.out.println(ans % mod);

	}

	public static void main(String[] args) throws Throwable {
		new Prac().solve();

	}

	public Prac() throws Throwable {
		if (test) {
			stream = new FileInputStream(testDataFile);
		}
	}

	InputStream stream = System.in;
	PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));// outStream

	public class ZKattio extends PrintWriter {
		public ZKattio(InputStream i) {
			super(new BufferedOutputStream(System.out));
			r = new BufferedReader(new InputStreamReader(i));
		}

		public ZKattio(InputStream i, OutputStream o) {
			super(new BufferedOutputStream(o));
			r = new BufferedReader(new InputStreamReader(i));
		}

		public boolean hasMoreTokens() {
			return peekToken() != null;
		}

		public int getInt() {
			return Integer.parseInt(nextToken());
		}

		public double getDouble() {
			return Double.parseDouble(nextToken());
		}

		public long getLong() {
			return Long.parseLong(nextToken());
		}

		public String getWord() {
			return nextToken();
		}

		private BufferedReader r;
		private String line;
		private StringTokenizer st;
		private String token;

		private String peekToken() {
			if (token == null)
				try {
					while (st == null || !st.hasMoreTokens()) {
						line = r.readLine();
						if (line == null)
							return null;
						st = new StringTokenizer(line);
					}
					token = st.nextToken();
				} catch (IOException e) {
				}
			return token;
		}

		private String nextToken() {
			String ans = peekToken();
			token = null;
			return ans;
		}
	}
	// System.out;

}

/*
Keep solving problems.
*/
import java.util.*;
import java.io.*;

public class CF478D {

    BufferedReader br;
    PrintWriter out;
    StringTokenizer st;
    boolean eof;
    final long MOD = 1000L * 1000L * 1000L + 7;
    void solve() throws IOException {
        int r = nextInt();
        int g = nextInt();

        int n = 100000 + 1;
        int[] arr0 = new int[n];
        int[] arr1 = new int[n];
        arr0[0] = 1;
        long res = 1;
        for(int i = 0; i < 1000; i++) {
            for(int j = 0; j < n; j++) {
                arr1[j] = 0;
            }
            for(int j = 0; j < n; j++) {
                if(arr0[j] == 0) {
                    continue;
                }
                arr1[j] += arr0[j];
                if(arr1[j] >= MOD) {
                    arr1[j] -= MOD;
                }
                if(j + i + 1 < n) {
                    arr1[j + i + 1] = arr0[j];
                    if (arr1[j + i + 1] >= MOD) {
                        arr1[j + i + 1] -= MOD;
                    }
                }
            }
            int sum = (i + 1) * (i + 2) / 2;
            long tmp = 0;
            for(int j = 0; j < n; j++) {
                if(j <= r && sum - j <= g) {
                    tmp += arr1[j];
                    if(tmp >= MOD) {
                        tmp -= MOD;
                    }
                }
            }
            if(tmp != 0) {
                res = tmp;
            }
            for(int j = 0; j < n; j++) {
                arr0[j] = arr1[j];
            }
        }
        out(res);
    }
    void shuffle(int[] a) {
        int n = a.length;
        for(int i = 0; i < n; i++) {
            int r = i + (int) (Math.random() * (n - i));
            int tmp = a[i];
            a[i] = a[r];
            a[r] = tmp;
        }
    }
    private void outln(Object o) {
        out.println(o);
    }
    private void out(Object o) {
        out.print(o);
    }
    public CF478D() 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 CF478D();
    }

    public long[] nextLongArr(int n) throws IOException{
        long[] res = new long[n];
        for(int i = 0; i < n; i++)
            res[i] = nextLong();
        return res;
    }
    public int[] nextIntArr(int n) throws IOException {
        int[] res = new int[n];
        for(int i = 0; i < n; i++)
            res[i] = nextInt();
        return res;
    }
    public String nextToken() {
        while (st == null || !st.hasMoreTokens()) {
            try {
                st = new StringTokenizer(br.readLine());
            } catch (Exception e) {
                eof = true;
                return null;
            }
        }
        return st.nextToken();
    }
    public String nextString() {
        try {
            return br.readLine();
        } catch (IOException e) {
            eof = true;
            return null;
        }
    }
    public int nextInt() throws IOException {
        return Integer.parseInt(nextToken());
    }
    public long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }
    public double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }
}

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

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author Aman Kumar Singh
 */
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);
        DRedGreenTowers solver = new DRedGreenTowers();
        solver.solve(1, in, out);
        out.close();
    }

    static class DRedGreenTowers {
        PrintWriter out;
        InputReader in;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            this.out = out;
            this.in = in;
            int r = ni();
            int g = ni();
            int n = 0;
            for (; ; n++) {
                if ((n * (n + 1)) / 2 > (r + g))
                    break;
            }
            long[][] dp = new long[2][r + 1];
            int i = 0, j = 0;
            dp[0][0] = 1;
            for (i = 1; i < n; i++) {
                int curr = i % 2;
                int hola = (i * (i + 1) / 2) - g;
                for (int red = Math.max(hola, 0); red <= r; red++) {
                    int green = (i * (i + 1)) / 2 - red;
                    dp[curr][red] = 0;
                    if (red >= i)
                        dp[curr][red] += dp[curr ^ 1][red - i];
                    if (green >= i)
                        dp[curr][red] += dp[curr ^ 1][red];
                    dp[curr][red] %= 1_000_000_007;
                }
            }

            long sum = 0;
            for (long x : dp[(n - 1) % 2]) {
                sum += x;
                sum %= 1_000_000_007;
            }
            pn(sum);
        }

        int ni() {
            return in.nextInt();
        }

        void pn(long zx) {
            out.println(zx);
        }

    }

    static class InputReader {
        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 UnknownError();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new UnknownError();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

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

        public String next() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            StringBuffer res = new StringBuffer();
            do {
                res.appendCodePoint(c);
                c = read();
            } while (!isSpaceChar(c));

            return res.toString();
        }

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

    }
}

/**
 * Created by Anna on 17.10.2014.
 */

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

public class TaskD {

    StringTokenizer st;
    BufferedReader in;
    PrintWriter out;

    public static void main(String[] args) throws NumberFormatException,
            IOException {
        TaskD solver = new TaskD();
        solver.open();
        solver.solve();
        solver.close();
    }

    public void open() throws IOException {
        in = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(System.out);
        //in = new BufferedReader(new FileReader("input.txt"));
        //out = new PrintWriter(new FileWriter("output.txt"));
    }

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

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

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

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

    boolean hasMoreTokens() throws IOException {
        while (st == null || !st.hasMoreTokens()) {
            String line = in.readLine();
            if (line == null)
                return false;
            st = new StringTokenizer(line);
        }
        return true;
    }

    int MOD = (int) (1e9 + 7);

    int g;
    int r;

    public void solve() throws NumberFormatException, IOException {
        g = nextInt();
        r = nextInt();
        if (r > g) {
            int tmp = r;
            r = g;
            g = tmp;
        }
        long[][] dp = new long[2][g + 1];

        int maxH = 0;
        int left = 0, right = (int) (4 * (1e5));
        while (right - left > 2) {
            int middle = (left + right) / 2;
            if (check(middle, r, g)) left = middle;
            else right = middle;
        }
        while (check(left, r, g)) left++;
        left--;
        maxH = left;

        Arrays.fill(dp[0], 0);
        if (r > 0) dp[0][g] = 1;
        dp[0][g - 1] = 1;
        boolean OK = true;
        int h;
        for (h = 2; h <= maxH; h++) {
            OK = false;
            int cnt = (h - 1) * h / 2;
            Arrays.fill(dp[(h & 1) ^ 1], 0);
            for (int green = 0; green <= g; green++) {
                if (dp[(h & 1)][green] == 0) continue;
                int red = r - (cnt - (g - green));
                if (red >= h) {
                    OK = true;
                    dp[(h & 1) ^ 1][green] += dp[(h & 1)][green];
                    if (dp[(h & 1) ^ 1][green] >= MOD) dp[(h & 1) ^ 1][green] -= MOD;
                }
                if (green >= h) {
                    OK = true;
                    dp[(h & 1) ^ 1][green - h] += dp[(h & 1)][green];
                    if (dp[(h & 1) ^ 1][green] >= MOD) dp[(h & 1) ^ 1][green] -= MOD;
                }
            }
        }
        long answ = 0;
        for (long cnt : dp[(maxH & 1) ^ 1]) {
            answ += cnt;
            if (answ >= MOD) answ -= MOD;
        }

        out.println(answ%MOD);
    }

    private boolean check(int height, int first, int second) {
        for (int i = height; i > 0; i--) {
            if (first < i && second < i) return false;
            if (first > second) first -= i;
            else second -= i;
        }
        return true;
    }

    public void close() {
        out.flush();
        out.close();
    }
}

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

/**
 * Codeforces 478D - Red-Green Towers
 * Created by Darren on 14-10-16.
 */
public class D {
    Reader in = new Reader(System.in);
    PrintWriter out = new PrintWriter(System.out);

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

    int r, g;
    final int MODULUS = 1000000007;
    int[] dp;

    void run() throws IOException {
        r = in.nextInt();
        g = in.nextInt();
        if (r > g) {
            int temp = r;
            r = g;
            g = temp;
        }

        int h = (int) ((Math.sqrt(8*(r+g)+1)-1)/2.0);
        dp = new int[r+1];
        dp[0] = 1;
        for (int i = 1; i <= h; i++) {
            for (int j = r-i; j >= 0; j--) {
                dp[i+j] += dp[j];
                if (dp[i+j] >= MODULUS)
                    dp[i+j] -= MODULUS;
            }
        }

        int total = h * (h + 1) / 2;
        long result = 0;
        for (int j = 0; j <= r; j++)
            result += dp[j];

        out.println(result % MODULUS);
        out.flush();
    }

    class Triple {
        int height;
        int green;
        int red;

        public Triple(int height, int green, int red) {
            this.height = height;
            this.green = green;
            this.red = red;
        }

        @Override
        public int hashCode() {
            return 31*31*height+31*green+red;
        }

        @Override
        public boolean equals(Object o) {
            if (o instanceof Triple) {
                Triple another = (Triple) o;
                if (height == another.height && green == another.green && red ==
                        another.red)
                    return true;
            }
            return false;
        }
    }

    static class Reader {
        BufferedReader reader;
        StringTokenizer tokenizer;

        public Reader(InputStream input) {
            reader = new BufferedReader(new InputStreamReader(input));
            tokenizer = new StringTokenizer("");
        }

        /** get next word */
        String nextToken() throws IOException {
            while ( ! tokenizer.hasMoreTokens() ) {
                //TODO add check for eof if necessary
                tokenizer = new StringTokenizer( reader.readLine() );
            }
            return tokenizer.nextToken();
        }

        String readLine() throws IOException {
            return reader.readLine();
        }

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

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

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

/* package whatever; // don't place package name! */

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

/* Name of the class has to be "Main" only if the class is public. */
public class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        Scanner sc = new Scanner(System.in);
        int mod = 1000000007;
        int r = sc.nextInt();
        int g = sc.nextInt();
        int n = (int)Math.floor((Math.pow(8*(r+g)+1, 0.5)-1)/2);
        int firstdp[] = new int[n*(n+1)/2+1];
        int seconddp[] = new int[n*(n+1)/2+1];
        int temp[] = new int[n*(n+1)/2+1];
        for(int i = 0;i<=n*(n+1)/2;i++){
            firstdp[i]=0;
            seconddp[i]=0;
        }
        firstdp[0]=1;
        seconddp[0]=1;
        seconddp[1]=1;
        for(int i = 2;i<n+1;i++){
            for(int j = 0;j<i;j++){
                temp[j]=seconddp[j];
                seconddp[j]=firstdp[j]%mod;
                firstdp[j]=temp[j];
            }
            for(int j = i;j<=i*(i+1)/2;j++){
                temp[j]=seconddp[j];
                seconddp[j]=(firstdp[j]%mod+firstdp[j-i]%mod)%mod;
                firstdp[j]=temp[j];
            }
        }
        /*for(int i = 0;i<=n;i++){
            for(int j = 0;j<=(n*(n+1))/2;j++){
                System.out.print(dp[i][j]);
            }
            System.out.println();
        }*/
        if(r>n*(n+1)/2){
            r=n*(n+1)/2;
        }
        if(g>n*(n+1)/2){
            g=n*(n+1)/2;
        }
        int lower = Math.max(0,n*(n+1)/2-g);
        int upper = Math.min(r,n*(n+1)/2);
        long answer = 0;
        for(int i = lower;i<=upper;i++){
            answer+=(long)(seconddp[i]%(long)mod);
        }
        System.out.println(answer);
        /*System.out.println("=============");
        System.out.println(lower + " " + upper);
        System.out.println("=============");
        System.out.println(n);*/
    }
}

/* package whatever; // don't place package name! */

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

/* Name of the class has to be "Main" only if the class is public. */
public class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        Scanner sc = new Scanner(System.in);
        int mod = 1000000007;
        int r = sc.nextInt();
        int g = sc.nextInt();
        int n = (int)Math.floor((Math.pow(8*(r+g)+1, 0.5)-1)/2);
        int firstdp[] = new int[n*(n+1)/2+1];
        int seconddp[] = new int[n*(n+1)/2+1];
        int temp[] = new int[n*(n+1)/2+1];
        for(int i = 0;i<=n*(n+1)/2;i++){
            firstdp[i]=0;
            seconddp[i]=0;
        }
        firstdp[0]=1;
        for(int i = 1;i<n+1;i++){
            for(int j = 0;j<i;j++){
                seconddp[j]=firstdp[j]%mod;
                temp[j]=seconddp[j];
            }
            for(int j = i;j<=i*(i+1)/2;j++){
                seconddp[j]=(firstdp[j]%mod+firstdp[j-i]%mod)%mod;
                temp[j]=seconddp[j];
            }
            for(int j = 0;j<=i*(i+1)/2;j++){
                firstdp[j]=temp[j];
            }

        /*for(int j = 0;j<=(n*(n+1))/2;j++){
                System.out.print(firstdp[j]);
            }
            System.out.println();
        for(int j = 0;j<=(n*(n+1))/2;j++){
                System.out.print(seconddp[j]);
            }
            System.out.println();*/
        }
        if(r>n*(n+1)/2){
            r=n*(n+1)/2;
        }
        if(g>n*(n+1)/2){
            g=n*(n+1)/2;
        }
        int lower = Math.max(0,n*(n+1)/2-g);
        int upper = Math.min(r,n*(n+1)/2);
        long answer = 0;
        for(int i = lower;i<=upper;i++){
            answer+=(long)(seconddp[i]%(long)mod);
        }
        System.out.println(answer);
        /*System.out.println("=============");
        System.out.println(lower + " " + upper);
        System.out.println("=============");
        System.out.println(n);*/
    }
}

import java.util.Arrays;
import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		D();
	}

	public static void A() {
		int s = 0;
		for (int index = 0; index < 5; ++index) {
			s += IO.readInt();
		}

		if (s > 0 && s % 5 == 0) {
			IO.println(s / 5);
		}
		else {
			IO.println(-1);
		}

	}

	public static void B() {
		long n = IO.readLong();
		long m = IO.readLong();

		long size = n / m;

		long kmin = pairs(size) * (m - (n - size * m)) + pairs(size + 1) * (n - size * m);
		long kmax = pairs(n - m + 1);

		IO.println(kmin + " " + kmax);
	}

	private static long pairs(long n) {
		return n * (n - 1) / 2;
	}

	public static void C() {
		long[] a = new long[3];
		for (int index = 0; index < 3; ++index) {
			a[index] = IO.readLong();
		}

		Arrays.sort(a);

		long ans = 0;
		if (a[2] >= (a[0] + a[1]) * 2) {
			ans = a[0] + a[1];
		}
		else {
			ans = (a[0] + a[1] + a[2]) / 3;
		}

		IO.println(ans);
	}

	public static void D() {
		int mod = 1000000007;

		long r = IO.readLong();
		long g = IO.readLong();

		if (r == 0 || g == 0) {
			IO.println(1);
		}

		int h = (int) (Math.sqrt(1d + 8 * (r + g)) - 1) / 2;

		int min = (int) Math.min(r, g);
		int max = (int) Math.max(r, g);

		int[] a = new int[min + 1];
		a[0] = 1;
		for (int i = 1; i <= h; ++i) {
            for (int j = min - i; j >= 0; j--) {
                a[i + j] += a[j];
                a[i + j] %= mod;
            }
		}

		int ans = 0;
		for (int index = Math.max(0, h * (h + 1) / 2 - max); index <= min; index++) {
			ans += a[index];
			ans %= mod;
		}
		IO.println(ans);
	}

	public static void E() {

	}

	//************* Input/Output *************//

	private static class IO {
		static {
			setUpScanner();
		}

		private static Scanner scanner;

		private static void setUpScanner() {
			scanner = new Scanner(new java.io.BufferedInputStream(System.in));
		};

		public static boolean isEmpty() {
			return !scanner.hasNext();
		}

		public static boolean hasNextLine() {
			return scanner.hasNextLine();
		}

		public static String readLine() {
			String line;
			try {
				line = scanner.nextLine();
			} catch (Exception e) {
				line = null;
			}
			return line;
		}

		public static String readString() {
			return scanner.next();
		}

		public static int readInt() {
			return scanner.nextInt();
		}

		public static double readDouble() {
			return scanner.nextDouble();
		}

		public static float readFloat() {
			return scanner.nextFloat();
		}

		public static long readLong() {
			return scanner.nextLong();
		}

		public static void print(Object o) {
			System.out.print(o.toString());
		}

		public static void println(Object o) {
			System.out.println(o);
		}
	}

	//************* Algorithms *************//

	private static class Algo {

		public static int binSearch(int[] array, int n, int lo, int hi) {
			if (lo > hi) {
				return lo;
			}

			int mid = lo + (hi - lo) /2;
			int cmp = (int) Math.signum(n - array[mid]);
			if (cmp < 0) {
				return binSearch(array, n, lo, mid - 1);
			}
			else if (cmp == 0) {
				return mid;
			}
			else {
				return binSearch(array, n, mid + 1, hi);
			}
		}

	}
}

public class D {

	public D () {
		int A = sc.nextInt(), B = sc.nextInt();

		int N = -1, S = A+B;
		for (int i : rep(1000))
			if (i*(i+1) <= 2*S)
				N = i;
		int Z = N*(N+1)/2;

		int [] P = new int [A+1]; P[0] = 1;
		for (int i : rep(N))
			for (int j = A; j >= i; --j)
				P[j] = (P[j] + P[j-i]) % MOD;

		int res = 0;
		for (int i : req(Z-B, A))
			res = (res + P[i]) % MOD;
		exit(res);
	}

	private static final int MOD = (int) 1e9 + 7;
	private static int [] rep(int N) { return rep(0, N); }
	private static int [] rep(int S, int T) { if (T <= S) return new int [0]; int [] res = new int [T-S]; for (int i = S; i < T; ++i) res[i-S] = i; return res; }
	private static int [] req(int S, int T) { return rep(S, T+1); }
	////////////////////////////////////////////////////////////////////////////////////
	private final static IOUtils.MyScanner sc = new IOUtils.MyScanner();
	private static void exit (Object o, Object ... A) { IOUtils.print(o, A); IOUtils.exit(); }
	private static class IOUtils {
		public static class MyScanner {
			public String next() { newLine(); return line[index++]; }
			public int nextInt() { return Integer.parseInt(next()); }
			//////////////////////////////////////////////
			private boolean eol() { return index == line.length; }
			private String readLine() {
				try {
					return r.readLine();
				} catch (Exception e) {
					throw new Error (e);
				}
			}
			private final java.io.BufferedReader r;
			private MyScanner () { this(new java.io.BufferedReader(new java.io.InputStreamReader(System.in))); }
			private MyScanner (java.io.BufferedReader r) {
				try {
					this.r = r;
					while (!r.ready())
						Thread.sleep(1);
					start();
				} catch (Exception e) {
					throw new Error(e);
				}
			}
			private String [] line;
			private int index;
			private void newLine() {
				if (line == null || eol()) {
					line = split(readLine());
					index = 0;
				}
			}
			private String [] split(String s) { return s.length() > 0 ? s.split(" ") : new String [0]; }
		}
		private static String build(Object o, Object ... A) { return buildDelim(" ", o, A); }
		private static String buildDelim(String delim, Object o, Object ... A) {
			StringBuilder b = new StringBuilder();
			append(b, o, delim);
			for (Object p : A)
				append(b, p, delim);
			return b.substring(delim.length());
		}
		//////////////////////////////////////////////////////////////////////////////////
		private static void start() { if (t == 0) t = millis(); }
		private static void append(StringBuilder b, Object o, String delim) {
			if (o.getClass().isArray()) {
				int len = java.lang.reflect.Array.getLength(o);
				for (int i = 0; i < len; ++i)
					append(b, java.lang.reflect.Array.get(o, i), delim);
			} else if (o instanceof Iterable<?>)
				for (Object p : (Iterable<?>) o)
					append(b, p, delim);
			else {
				if (o instanceof Double)
					o = new java.text.DecimalFormat("#.############").format(o);
				b.append(delim).append(o);
			}
		}
		private static java.io.PrintWriter pw = new java.io.PrintWriter(System.out);
		private static void print(Object o, Object ... A) { pw.println(build(o, A)); }
		private static void err(Object o, Object ... A) { System.err.println(build(o, A)); }
		private static void exit() {
			IOUtils.pw.close();
			System.out.flush();
			err("------------------");
			err(IOUtils.time());
			System.exit(0);
		}
		private static long t;
		private static long millis() { return System.currentTimeMillis(); }
		private static String time() { return "Time: " + (millis() - t) / 1000.0; }
	}
	public static void main (String[] args) { new D(); IOUtils.exit(); }
}

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

public class Main
{

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int r = in.nextInt();
        int g = in.nextInt();
        long dp[][] = new long[200010][2];
        double D = 1 - 4*(-2*r - 2*g);
        //System.out.println("D = " + D);
        long h = (long)((Math.sqrt(D) - 1)/2);
        //System.out.println("h = " + h);
        long ans = 0;
        if(r > 0)
            dp[r - 1][0] = 1;
        if(g > 0)
            dp[r][0] = 1;
        for(int i = 2; i <= h; i++)
        {
            for(int j = r; j >= 0; j--)
            {
                dp[j][(i%2 == 1) ? 0 : 1] = dp[j][(i%2 == 1) ? 1 : 0];
                if(j+i <= r)
                    dp[j][(i%2 == 1) ? 0 : 1] += dp[j+i][(i%2 == 1) ? 1 : 0];
            }
        }
        for(int i = 0; i<=r; i++)
        {
            if(h*(h+1)/2 - r + i <= g)
                ans += dp[i][(h%2 == 1) ? 0 : 1];
            //System.out.println("dp[" + i + "] = " + dp[i][(h%2 == 1) ? 0 : 1]);
        }
        System.out.println(ans);

    }

}

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

public class RedGreen_Single{
	int blockCount(int h){
		return (h*(h+1)/2);
	}
	int findCount(int R, int G){
		int g;
		int mod = 1000*1000*1000+7;
		int sum=0;
		int maxHeight = (int)((Math.sqrt(1+8*(R+G))-1)/2);
		//System.out.println(maxHeight);
		int count[]=new int [R+1];
		count[R]=1;
		for(int j=1;j<=maxHeight;j++){
			for(int i=0;i<=R;i++){
				int c=0;
				g=R+G-i-blockCount(j);
				if(g>=0 && (i+j)<=R){
					c=count[i+j];
				}
				if(g>=0)
					c+=count[i];
				count[i]=c%mod;
			}

		}

		/*for(int i=0;i<=R;i++){
					System.out.println(count[i]);
		}*/

		for(int i=0;i<=R;i++)
				sum+=count[i];

		return (int)(sum%mod);
	}

	public static void main(String [] args){
		Scanner sc = new Scanner(System.in);
		RedGreen_Single obj = new RedGreen_Single();
		int r = sc.nextInt();
		int g = sc.nextInt();
		System.out.println(obj.findCount(r,g));
	}
}

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

public class RedGreen_Self{
	int blockCount(int h){
		return (h*(h+1)/2);
	}
	int findCount(int R, int G){
		int g;
		int sum=0;
		int maxHeight = (int)((Math.sqrt(1+8*(R+G))-1)/2);
		//System.out.println(maxHeight);
		int count[][]=new int [R+1][maxHeight+1];
		for(int i=0;i<R;i++){
			count[i][0]=0;
		}
		count[R][0]=1;
		for(int j=1;j<=maxHeight;j++){
			for(int i=0;i<=R;i++){
				g=R+G-i-blockCount(j);
				if(g>=0 && (i+j)<=R){
					count[i][j]+=count[i+j][j-1];
				}
				if(g>=0)
					count[i][j]+=count[i][j-1];

			}

		}

		/*for(int i=0;i<=R;i++){
			for(int j=0;j<=maxHeight;j++){
				System.out.print(count[i][j]+" ");
			}
			System.out.println();
		}
		*/
		for(int i=0;i<R;i++)
			sum+=count[i][maxHeight];

		return sum;
	}

	public static void main(String [] args){
		Scanner sc = new Scanner(System.in);
		RedGreen_Self obj = new RedGreen_Self();
		int r = sc.nextInt();
		int g = sc.nextInt();
		System.out.println(obj.findCount(r,g));
	}
}

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

public class RedGreen_Single{
	int blockCount(int h){
		return (h*(h+1)/2);
	}
	long findCount(int R, int G){
		int g;
		long sum=0;
		int maxHeight = (int)((Math.sqrt(1+8*(R+G))-1)/2);
		//System.out.println(maxHeight);
		long count[]=new long [R+1];
		for(int i=0;i<R;i++){
			count[i]=0;
		}
		count[R]=1;
		for(int j=1;j<=maxHeight;j++){
			for(int i=0;i<=R;i++){
				long c=0;
				g=R+G-i-blockCount(j);
				if(g>=0 && (i+j)<=R){
					c+=count[i+j];
				}
				if(g>=0)
					c+=count[i];
				count[i]=c;
			}

		}

		/*for(int i=0;i<=R;i++){
					System.out.println(count[i]);
		}*/

		for(int i=0;i<=R;i++)
				sum+=count[i];

		return sum;
	}

	public static void main(String [] args){
		Scanner sc = new Scanner(System.in);
		RedGreen_Single obj = new RedGreen_Single();
		int r = sc.nextInt();
		int g = sc.nextInt();
		System.out.println(obj.findCount(r,g));
	}
}

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

public class RedGreen_Single{
	int blockCount(int h){
		return (h*(h+1)/2);
	}
	int findCount(int R, int G){
		int g;
		int mod = 1000*1000*1000+7;
		long sum=0;
		int maxHeight = (int)((Math.sqrt(1+8*(R+G))-1)/2);
		//System.out.println(maxHeight);
		long count[]=new long [R+1];
		for(int i=0;i<R;i++){
			count[i]=0;
		}
		count[R]=1;
		for(int j=1;j<=maxHeight;j++){
			for(int i=0;i<=R;i++){
				long c=0;
				g=R+G-i-blockCount(j);
				if(g>=0 && (i+j)<=R){
					c=count[i+j];
				}
				if(g>=0)
					c+=count[i];
				count[i]=c;
			}

		}

		/*for(int i=0;i<=R;i++){
					System.out.println(count[i]);
		}*/

		for(int i=0;i<=R;i++)
				sum+=count[i];

		return (int)(sum%mod);
	}

	public static void main(String [] args){
		Scanner sc = new Scanner(System.in);
		RedGreen_Single obj = new RedGreen_Single();
		int r = sc.nextInt();
		int g = sc.nextInt();
		System.out.println(obj.findCount(r,g));
	}
}

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.StringTokenizer;

public class R273D2D {
    static int totalBlock, maxH;
    static int[] dp;
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int rr = Integer.parseInt(st.nextToken());
        int gg = Integer.parseInt(st.nextToken());
        maxH=1;
        while(maxH*(maxH+1)/2<=rr+gg){
            maxH++;
        }
        maxH--;
        totalBlock = rr+gg;
        dp = new int[rr+1];
        for(int h=0; h<=maxH; h++){
            int[] tmp = new int[rr+1];
            for(int r=0; r<=rr; r++){
                int g = (totalBlock-(maxH-h)*(maxH+h+1)/2) - r;
                if(g<0) continue;
                if(r==0 || g==0 || h==0) tmp[r]=1; else{
                    if(r>=h) tmp[r] += dp[r-h];
                    if(g>=h) tmp[r] += dp[r];
                }
            }
            dp = tmp;
        }
        System.out.println(dp[rr]);
    }
}

import java.util.Scanner;

public class D {
    static int r;
    static int g;
    static long dp [][];
    public static void main (String [] args) {
        Scanner sc = new Scanner(System.in);

        r = sc.nextInt();
        g = sc.nextInt();

        dp = new long[2][r+1];
        if(r > 0)
            dp[0][1] = 1;
        if(g > 0)
            dp[0][0] = 1;

        for(int h = 2; h <= 900 ; h++) {
            boolean update = false;
            for(int red = dp[0].length-1 ; red >= 0; red--) {
                int green = (h * (h-1)) / 2 - red;
                if(red - h >= 0 && dp[0][red-h] > 0) {
                    dp[1][red] = dp[0][red-h];
                    update = true;
                } else {
                    dp[1][red] = 0;
                }

                if(green+h <= g) {
                    dp[1][red] += dp[0][red];
                    update = true;
                }
            }
            if(!update) {
                break;
            } else {
                long [] val = dp[0];
                dp[0] = dp[1];
                dp[1] = val;
            }
        }
        long result = 0;
        for(int i = 0 ; i < dp[0].length; i++) {
            result += dp[0][i];
            if(result >= 1000000007) {
                result -= 1000000007;
            }
        }
        System.out.println(result);
    }
}

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;

public final class RedGreenTowers {

	static int MOD = 1000000000 + 7;

	static class Reader {
		final private int BUFFER_SIZE = 1 << 16;
		private DataInputStream din;
		private byte[] buffer;
		private int bufferPointer, bytesRead;

		public Reader() {
			din = new DataInputStream(System.in);
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}

		public Reader(String file_name) throws IOException {
			din = new DataInputStream(new FileInputStream(file_name));
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}

		public String readLine() throws IOException {
			byte[] buf = new byte[64]; // line length
			int cnt = 0, c;
			while ((c = read()) != -1) {
				if (c == '\n')
					break;
				buf[cnt++] = (byte) c;
			}
			return new String(buf, 0, cnt);
		}

		public int nextInt() throws IOException {
			int ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do {
				ret = ret * 10 + c - '0';
			} while ((c = read()) >= '0' && c <= '9');

			if (neg)
				return -ret;
			return ret;
		}

		public long nextLong() throws IOException {
			long ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do {
				ret = ret * 10 + c - '0';
			} while ((c = read()) >= '0' && c <= '9');
			if (neg)
				return -ret;
			return ret;
		}

		public double nextDouble() throws IOException {
			double ret = 0, div = 1;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();

			do {
				ret = ret * 10 + c - '0';
			} while ((c = read()) >= '0' && c <= '9');

			if (c == '.') {
				while ((c = read()) >= '0' && c <= '9') {
					ret += (c - '0') / (div *= 10);
				}
			}
			if (neg)
				return -ret;
			return ret;
		}

		private void fillBuffer() throws IOException {
			bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
			if (bytesRead == -1)
				buffer[0] = -1;
		}

		private byte read() throws IOException {
			if (bufferPointer == bytesRead)
				fillBuffer();
			return buffer[bufferPointer++];
		}

		public void close() throws IOException {
			if (din == null)
				return;
			din.close();
		}
	}

	public static int maxHeight(int r, int g, int level) {
		int height = 0;
		if (r - level >= 0) {
			height = Math.max(height, maxHeight(r - level, g, level + 1) + 1);
		}
		if (g - level >= 0) {
			height = Math.max(height, maxHeight(r, g - level, level + 1) + 1);
		}
		return height;
	}

	static int numcalled;

	public static long numWays(int r, int g, int level) {
		numcalled += 1;
		if (r < 0 || g < 0 || level <= 0)
			return 0;

		if (level == 1 && r >= 1 && g >= 1)
			return 2;

		if (level == 1 && r >= 1)
			return 1;

		if (level == 1 && g >= 1)
			return 1;

		return ((numWays(r - level, g, level - 1) % MOD) + (numWays(r, g - level, level - 1) % MOD)) % MOD;
	}

	public static int nC2(int n) {
		return n * (n + 1) / 2;
	}

	public static void main(String[] args) throws IOException {
		Reader input = new Reader();
		int r = input.nextInt();
		int g = input.nextInt();

		int height = 1;
		while (nC2(height) <= r + g) {
			height += 1;
		}
		height -= 1;

		int dp[][] = new int[height + 1][Math.max(r, g) + 1];

		for (int i = 1; i <= height; i += 1)
			dp[i][0] = 1;

		dp[1][1] = 1;

		for (int i = 2; i <= height; i += 1) {
			for (int j = 1; j < dp[i].length; j += 1) {
				dp[i][j] = (dp[i - 1][j] + (j >= i ? dp[i - 1][j - i] : 0)) % MOD;
			}
		}

		int extra = r + g - nC2(height);
		// System.out.println(height + " " + extra);

		int max = Math.max(r, g);
		int ans = 0;
		for (int i = 0; i <= extra; i += 1) {
			if (max - extra > 0) {
				ans = (ans + dp[height][max - extra]) % MOD;
			}
		}
		System.out.println(ans);
	}
}

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;

public final class RedGreenTowers {

	static int MOD = 1000000000 + 7;

	static class Reader {
		final private int BUFFER_SIZE = 1 << 16;
		private DataInputStream din;
		private byte[] buffer;
		private int bufferPointer, bytesRead;

		public Reader() {
			din = new DataInputStream(System.in);
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}

		public Reader(String file_name) throws IOException {
			din = new DataInputStream(new FileInputStream(file_name));
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}

		public String readLine() throws IOException {
			byte[] buf = new byte[64]; // line length
			int cnt = 0, c;
			while ((c = read()) != -1) {
				if (c == '\n')
					break;
				buf[cnt++] = (byte) c;
			}
			return new String(buf, 0, cnt);
		}

		public int nextInt() throws IOException {
			int ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do {
				ret = ret * 10 + c - '0';
			} while ((c = read()) >= '0' && c <= '9');

			if (neg)
				return -ret;
			return ret;
		}

		public long nextLong() throws IOException {
			long ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do {
				ret = ret * 10 + c - '0';
			} while ((c = read()) >= '0' && c <= '9');
			if (neg)
				return -ret;
			return ret;
		}

		public double nextDouble() throws IOException {
			double ret = 0, div = 1;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();

			do {
				ret = ret * 10 + c - '0';
			} while ((c = read()) >= '0' && c <= '9');

			if (c == '.') {
				while ((c = read()) >= '0' && c <= '9') {
					ret += (c - '0') / (div *= 10);
				}
			}
			if (neg)
				return -ret;
			return ret;
		}

		private void fillBuffer() throws IOException {
			bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
			if (bytesRead == -1)
				buffer[0] = -1;
		}

		private byte read() throws IOException {
			if (bufferPointer == bytesRead)
				fillBuffer();
			return buffer[bufferPointer++];
		}

		public void close() throws IOException {
			if (din == null)
				return;
			din.close();
		}
	}

	public static int maxHeight(int r, int g, int level) {
		int height = 0;
		if (r - level >= 0) {
			height = Math.max(height, maxHeight(r - level, g, level + 1) + 1);
		}
		if (g - level >= 0) {
			height = Math.max(height, maxHeight(r, g - level, level + 1) + 1);
		}
		return height;
	}

	static int numcalled;

	public static long numWays(int r, int g, int level) {
		numcalled += 1;
		if (r < 0 || g < 0 || level <= 0)
			return 0;

		if (level == 1 && r >= 1 && g >= 1)
			return 2;

		if (level == 1 && r >= 1)
			return 1;

		if (level == 1 && g >= 1)
			return 1;

		return ((numWays(r - level, g, level - 1) % MOD) + (numWays(r, g - level, level - 1) % MOD)) % MOD;
	}

	public static int nC2(int n) {
		return n * (n + 1) / 2;
	}

	public static void main(String[] args) throws IOException {
		Reader input = new Reader();
		int r = input.nextInt();
		int g = input.nextInt();

		int height = 1;
		while (nC2(height) <= r + g) {
			height += 1;
		}
		height -= 1;

		int dp[][] = new int[height + 1][Math.max(r, g) + 1];

		for (int i = 1; i <= height; i += 1)
			dp[i][0] = 1;

		dp[1][1] = 1;

		for (int i = 2; i <= height; i += 1) {
			for (int j = 1; j < dp[i].length; j += 1) {
				dp[i][j] = (dp[i - 1][j] + (j >= i ? dp[i - 1][j - i] : 0)) % MOD;
			}
		}

		int extra = r + g - nC2(height);
		// System.out.println(height + " " + extra);

		int max = Math.max(r, g);
		int ans = 0;
		for (int i = 0; i <= extra; i += 1) {
			if (max - extra >= 0) {
				ans = (ans + dp[height][max - extra]) % MOD;
			}
		}
		System.out.println(ans);
	}
}

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;

public final class RedGreenTowers {

	static int MOD = 1000000000 + 7;

	static class Reader {
		final private int BUFFER_SIZE = 1 << 16;
		private DataInputStream din;
		private byte[] buffer;
		private int bufferPointer, bytesRead;

		public Reader() {
			din = new DataInputStream(System.in);
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}

		public Reader(String file_name) throws IOException {
			din = new DataInputStream(new FileInputStream(file_name));
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}

		public String readLine() throws IOException {
			byte[] buf = new byte[64]; // line length
			int cnt = 0, c;
			while ((c = read()) != -1) {
				if (c == '\n')
					break;
				buf[cnt++] = (byte) c;
			}
			return new String(buf, 0, cnt);
		}

		public int nextInt() throws IOException {
			int ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do {
				ret = ret * 10 + c - '0';
			} while ((c = read()) >= '0' && c <= '9');

			if (neg)
				return -ret;
			return ret;
		}

		public long nextLong() throws IOException {
			long ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do {
				ret = ret * 10 + c - '0';
			} while ((c = read()) >= '0' && c <= '9');
			if (neg)
				return -ret;
			return ret;
		}

		public double nextDouble() throws IOException {
			double ret = 0, div = 1;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();

			do {
				ret = ret * 10 + c - '0';
			} while ((c = read()) >= '0' && c <= '9');

			if (c == '.') {
				while ((c = read()) >= '0' && c <= '9') {
					ret += (c - '0') / (div *= 10);
				}
			}
			if (neg)
				return -ret;
			return ret;
		}

		private void fillBuffer() throws IOException {
			bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
			if (bytesRead == -1)
				buffer[0] = -1;
		}

		private byte read() throws IOException {
			if (bufferPointer == bytesRead)
				fillBuffer();
			return buffer[bufferPointer++];
		}

		public void close() throws IOException {
			if (din == null)
				return;
			din.close();
		}
	}

	public static int maxHeight(int r, int g, int level) {
		int height = 0;
		if (r - level >= 0) {
			height = Math.max(height, maxHeight(r - level, g, level + 1) + 1);
		}
		if (g - level >= 0) {
			height = Math.max(height, maxHeight(r, g - level, level + 1) + 1);
		}
		return height;
	}

	static int numcalled;

	public static long numWays(int r, int g, int level) {
		numcalled += 1;
		if (r < 0 || g < 0 || level <= 0)
			return 0;

		if (level == 1 && r >= 1 && g >= 1)
			return 2;

		if (level == 1 && r >= 1)
			return 1;

		if (level == 1 && g >= 1)
			return 1;

		return ((numWays(r - level, g, level - 1) % MOD) + (numWays(r, g - level, level - 1) % MOD)) % MOD;
	}

	public static int nC2(int n) {
		return n * (n + 1) / 2;
	}

	public static void main(String[] args) throws IOException {
		Reader input = new Reader();
		int r = input.nextInt();
		int g = input.nextInt();

		int height = 1;
		while (nC2(height) <= r + g) {
			height += 1;
		}
		height -= 1;

		int dp[][] = new int[height + 1][Math.max(r, g) + 1];

		for (int i = 1; i <= height; i += 1)
			dp[i][0] = 1;

		dp[1][1] = 1;

		for (int i = 2; i <= height; i += 1) {
			for (int j = 1; j < dp[i].length; j += 1) {
				dp[i][j] = (dp[i - 1][j] + (j >= i ? dp[i - 1][j - i] : 0)) % MOD;
			}
		}

		int extra = r + g - nC2(height);
		// System.out.println(height + " " + extra);

		int min = Math.min(r, g);
		int ans = 0;
		for (int i = 0; i <= extra; i += 1) {
			if (min - extra >= 0) {
				ans = (ans + dp[height][min - extra]) % MOD;
			}
		}
		System.out.println(ans);
	}
}

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

/**
 * 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;
        Scanner in = new Scanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        DRedGreenTowers solver = new DRedGreenTowers();
        solver.solve(1, in, out);
        out.close();
    }

    static class DRedGreenTowers {
        static int mod = (int) 1e9 + 7;

        public void solve(int testNumber, Scanner sc, PrintWriter pw) {
            int r = sc.nextInt(), g = sc.nextInt(), maxH = bs(r, g);
            int[][] dp = new int[2][r + 1];
            dp[0][r] = 1;
            int cur = 1;
            for (int i = 0; i < maxH; i++, cur ^= 1) {
                Arrays.fill(dp[cur], 0);
                for (int red = 0; red <= r; red++) {
                    int green = g - ((i) * (i + 1) / 2) + (r - red);
                    if (red >= i + 1)
                        dp[cur][red - (i + 1)] += dp[cur ^ 1][red];
                    if (green >= i + 1)
                        dp[cur][red] += dp[cur ^ 1][red];
                }
            }
            long ans = 0;
            for (int i = 0; i <= r; i++) {
                int green = maxH - (r - i);
                if (green > g)
                    continue;
                ans += dp[cur ^ 1][i];
                ans %= mod;
            }
            pw.println(ans);
        }

        private int bs(int r, int g) {
            int l = 0, h = (int) 1e3, toRet = -1;
            while (l <= h) {
                int mid = (l + h) / 2;
                if ((mid * (mid + 1) / 2) > r + g)
                    h = mid - 1;
                else {
                    l = mid + 1;
                    toRet = mid;
                }
            }
            return toRet;
        }

    }

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;

        public Scanner(FileReader r) {
            br = new BufferedReader(r);
        }

        public Scanner(InputStream s) {
            br = new BufferedReader(new InputStreamReader(s));
        }

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

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

    }
}

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

/**
 * 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;
        Scanner in = new Scanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        DRedGreenTowers solver = new DRedGreenTowers();
        solver.solve(1, in, out);
        out.close();
    }

    static class DRedGreenTowers {
        static int r;
        static int g;
        static int maxH;
        static Integer[][] memo;

        public int dp(int level, int red) {
            if (level == maxH)
                return 1;
            if (memo[level][red] != null)
                return memo[level][red];
            int green = (level) * (level + 1) / 2 - (r - red);
            int takeGreen = green >= level ? dp(level + 1, red) : 0;
            int takeRed = red >= level ? dp(level + 1, red - level) : 0;
            return memo[level][red] = takeGreen + takeRed;
        }

        public void solve(int testNumber, Scanner sc, PrintWriter pw) {
            r = sc.nextInt();
            g = sc.nextInt();
            maxH = bs();
            memo = new Integer[maxH][r + 1];
            pw.println(dp(0, r));
        }

        private int bs() {
            int l = 0, h = (int) 1e3, toRet = -1;
            while (l <= h) {
                int mid = (l + h) / 2;
                if ((mid * (mid + 1) / 2) > r + g)
                    h = mid - 1;
                else {
                    l = mid + 1;
                    toRet = mid;
                }
            }
            return toRet;
        }

    }

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;

        public Scanner(FileReader r) {
            br = new BufferedReader(r);
        }

        public Scanner(InputStream s) {
            br = new BufferedReader(new InputStreamReader(s));
        }

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

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

    }
}

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

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author Abhas Jain
 */
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);
        DRedGreenTowers solver = new DRedGreenTowers();
        solver.solve(1, in, out);
        out.close();
    }

    static class DRedGreenTowers {
        static long mod = (long) 1e9 + 7L;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int r = in.ni();
            int g = in.ni();
            int h = (int) Math.sqrt(2 * (r + g));
            if (h * h == 2 * (r + g)) h--;
            long[] dp = new long[r + 1];
            dp[0] = 1;
            for (int i = 1; i <= h; ++i) {
                for (int j = r; j >= i; --j) {
                    dp[j] += dp[j - i];
                    dp[j] %= mod;
                }
            }
            long ans = 0;
            for (int i = 0; i <= r; ++i) {
                if ((h * (h + 1)) / 2 - i <= g) {
                    ans += dp[i];
                    ans %= mod;
                }
            }
            out.print(ans);
        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

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

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

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

    }
}

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

/**
 * 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);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        int R;
        int G;
        static final long MOD = (long) (1e9 + 7);

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            R = in.nextInt();
            G = in.nextInt();
            int H = (int) (-1 + Math.sqrt(1 + 8 * (R + G))) / 2;

            long[][] dp = new long[2][R + 1];
            if (G > 0)
                dp[0][R] = 1;
            if (R > 0)
                dp[0][R - 1] = 1;
            int pred = 0, cur = 1;
            for (int h = 2; h <= H; h++) {
                int total = (h * (h + 1)) >> 1;
                for (int r = 0; r <= R; r++) {
                    int g = total - (R - r);
                    if (g < 0 || g > G) {
                        dp[cur][r] = 0;
                        continue;
                    } else {
                        dp[cur][r] = dp[pred][r] % MOD;
                    }
                    if (r + h <= R)
                        dp[cur][r] = (dp[cur][r] + dp[pred][r + h]) % MOD;
                }
                int t = pred;
                pred = cur;
                cur = t;
            }

            long ans = 0;
            for (int i = 0; i < dp.length; i++)
                ans = (ans + dp[pred][i]) % MOD;
            out.println(ans);
        }

    }

    static class InputReader {
        final InputStream is;
        final byte[] buffer = new byte[1024];
        int curCharIdx;
        int nChars;

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

        public int read() {
            if (curCharIdx >= nChars) {
                try {
                    curCharIdx = 0;
                    nChars = is.read(buffer);
                    if (nChars == -1)
                        return -1;
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return buffer[curCharIdx++];
        }

        public int nextInt() {
            int sign = 1;
            int c = skipDelims();
            if (c == '-') {
                sign = -1;
                c = read();
                if (isDelim(c))
                    throw new RuntimeException("Incorrect format");
            }
            int val = 0;
            while (c != -1 && !isDelim(c)) {
                if (!isDigit(c))
                    throw new RuntimeException("Incorrect format");
                val = 10 * val + (c - '0');
                c = read();
            }
            return val * sign;
        }

        private final int skipDelims() {
            int c = read();
            while (isDelim(c)) {
                c = read();
            }
            return c;
        }

        private static boolean isDelim(final int c) {
            return c == ' ' ||
                    c == '\n' ||
                    c == '\t' ||
                    c == '\r' ||
                    c == '\f';
        }

        private static boolean isDigit(final int c) {
            return '0' <= c && c <= '9';
        }

    }
}

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;
import java.util.Stack;
import java.util.StringTokenizer;

public class Main {
	static boolean can (int r , int g , int h) {
		while (h > 0 && (r > 0 || g > 0) && (r >= h || g >= h)) {
			if (r < g) {
				if (r >= h)
					r -= h;
				else g -= h;
			}

			else if (g >= h)
				g -= h;
			else r -= h;
			h -- ;
		}
		return h <= 0;
	}
	static int getH (int r , int g) {
		int lo = 0 ;
		int hi = (int)1e5;
		int max = 0;
		for(int i = 0 ; i < 20 ; ++i) {
			int mid = lo + ((hi - lo) >> 1);
			if (can(r , g , mid)) {
				max = Math.max(max, mid);
				lo = mid + 1;
			}
			else hi = mid - 1 ;
		}
		return max;
	}

	public static void main(String[] args) throws Exception {
		Scanner sc = new Scanner(System.in);
		int r = sc.nextInt();
		int g = sc.nextInt();
		int H = getH (r , g);
		int last [] = new int[r + 1];
		int dp [] = new int[r + 1];
		last[0] = 1;
		for (int curH = 1 ; curH <= H ; ++ curH) {
			dp = new int[r + 1];
			for (int red = 0 ; red <= r ; ++ red) {
				if (red >= curH)
					dp[red] += last[red - curH];

				int neededBlocksSoFar = ((curH) * (curH + 1)) >> 1;
				if (g >= neededBlocksSoFar - red) dp[red] += last[red];
			}
			for (int i = 0 ; i <= r ; ++ i)
				last[i] = dp[i];
		}
		int cnt = 0 ;
		for (int i = 0 ; i <= r ; ++ i) {
			cnt += last[i];
		}
		System.out.println(cnt);
	}

}

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static int g, r, mxH;
    public static int memo[][] = new int[2][200001];
    public static int mod = 1000000007;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        r = scanner.nextInt();
        g = scanner.nextInt();
        mxH = (int) Math.sqrt(r + g);
        if (((mxH + 1) * (mxH + 2)) / 2 <= r + g)
            ++mxH;
        for (int i = 0; i <= g; ++i)
            memo[mxH % 2][i] = 1;
        for (int idx = mxH - 1; idx >= 0; --idx)
            for (int remG = 0; remG <= g; ++remG) {
                int remR = r - (((idx * (idx + 1)) / 2) - (g - remG));
                if (remR < 0)
                    continue;
                int val1 = 0, val2 = 0;
                if (remG >= idx + 1)
                    val1 = memo[(idx + 1) % 2][remG - idx - 1];
                if (remR >= idx + 1)
                    val2 = memo[(idx + 1) % 2][remG];
                memo[idx % 2][remG] = (val1 + val2) % mod;
            }
        System.out.println(memo[0][g]);
    }
}

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static int g, r, mxH;
    public static int memo[][] = new int[2][200001];
    public static int mod = 1000000007;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        r = scanner.nextInt();
        g = scanner.nextInt();
        mxH = 0;
        while (true) {
            if ((mxH * (mxH + 1)) / 2 <= r + g)
                ++mxH;
            else
                break;
        }
        for (int i = 0; i <= g; ++i)
            memo[mxH % 2][i] = 1;
        for (int idx = mxH - 1; idx >= 0; --idx)
            for (int remG = 0; remG <= g; ++remG) {
                int remR = r - (((idx * (idx + 1)) / 2) - (g - remG));
                if (remR < 0)
                    continue;
                int val1 = 0, val2 = 0;
                if (remG >= idx + 1)
                    val1 = memo[(idx + 1) % 2][remG - idx - 1];
                if (remR >= idx + 1)
                    val2 = memo[(idx + 1) % 2][remG];
                memo[idx % 2][remG] = (val1 + val2) % mod;
            }
        System.out.println(memo[0][g]);
    }
}

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static int g, r, mxH;
    public static int memo[][] = new int[2][200001];

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        r = scanner.nextInt();
        g = scanner.nextInt();
        mxH = (int) Math.sqrt(r + g);
        if (((mxH + 1) * (mxH + 2)) / 2 <= r + g)
            ++mxH;
        for (int i = 0; i <= g; ++i)
            memo[mxH % 2][i] = 1;
        for (int idx = mxH - 1; idx >= 0; --idx)
            for (int remG = 0; remG <= g; ++remG) {
                int remR = r - (((idx * (idx + 1)) / 2) - (g - remG));
                if (remR < 0)
                    continue;
                int val1 = 0, val2 = 0;
                if (remG >= idx + 1)
                    val1 = memo[(idx + 1) % 2][remG - idx - 1];
                if (remR >= idx + 1)
                    val2 = memo[(idx + 1) % 2][remG];
                memo[idx % 2][remG] = val1 + val2;
            }
        System.out.println(memo[0][g]);
    }
}

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

public class L {

	static int mod = (int) (1e9 + 7);

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

		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		int h = maxl(n, m);
		int[][] a = new int[2][n + 1];
		a[0][n] = 1;
		int cur = 0;
		for (int i = 1; i <= h; i++) {
			Arrays.fill(a[cur ^ 1], 0);
			for (int j = 0; j < n + 1; j++) {
				int g = m - (i - 1) * i / 2 + (n - j);
				if (j >= i) {
					a[cur ^ 1][j - i] += a[cur][j] & mod;
				}
				if (g >= i) {
					a[cur ^ 1][j] += a[cur][j] % mod;
				}
			}
			cur ^= 1;

		}
		long sum = 0;
		for (int i = 0; i <= n; i++) {
			sum += a[cur][i];
			sum %= mod;
		}
		System.out.println(sum);

		pw.flush();
	}

	static int maxl(int r, int g) {
		int s = 0;
		int e = 1000;
		int ans = -1;
		while (s <= e) {
			int mid = s + e >> 1;
			if (mid * (mid + 1) / 2 <= r + g) {
				ans = mid;
				s = mid + 1;
			} else
				e = mid - 1;

		}
		return ans;
	}
}

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.StringTokenizer;

public class CF_273D {

    static final long mod = 1000000007L;

    static ArrayList<Integer> h = new ArrayList<Integer>();

    static long[][] res;

    public static long get(int r, int g){
        if(r<0 || g<0) return 0;
        if(res[r][g]!=0)
            return res[r][g];

        int actH = Collections.binarySearch(h, r+g);

        if(actH<0)
            actH = -actH -2;

        res[r][g] = (get(r-(actH+1),g) + get(r,g-(actH+1)))%mod;

        return res[r][g];
    }

    public static void main(String[] args) {
        FastScanner sc = new FastScanner(System.in);
        int r = sc.nextInt();
        int g = sc.nextInt();

        res = new long[r+1][g+1];

        h.add(1);

        while(h.get(h.size()-1)<300000){
            h.add((((h.size()+1)*(h.size()+2))/2));
        }

        for (int i=1; i<=r; i++)
            res[i][0] = 1;

        for (int i=1; i<=g; i++)
            res[0][i] = 1;

        System.out.println(get(r,g));
    }

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner(File f) {
            try {
                br = new BufferedReader(new FileReader(f));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

        public FastScanner(InputStream f) {
            br = new BufferedReader(new InputStreamReader(f));
        }

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

        boolean hasMoreTokens() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return false;
                st = new StringTokenizer(s);
            }
            return true;
        }

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

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

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

}

import java.util.Scanner;

public class RedGreenTowers {
	public static int MOD = (int) (1e9 + 7);

	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int R = scan.nextInt();
		int G = scan.nextInt();
		int H = 0;
		for (int i = 1; i <= 1000; i++)
			if ((i * (i + 1) / 2) > R + G) {
				H = i - 1;
				break;
			}
		long[] dp = new long[R + 1];
		dp[0] = 1;
		for (int i = 1; i <= H; i++)
			for (int j = R - i; j >= 0; j--) {
				dp[j + i] += dp[j];
				if (dp[j + 1] >= MOD)
					dp[j + 1] -= MOD;
			}

		long answer = 0;
		for (int i = 0; i <= R; i++) {
			if (H * (H + 1) / 2 - i <= G)
				answer += dp[i];
		}
		System.out.println(answer % MOD);
		scan.close();

	}
}

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

public class RedGreenTowers {

	static class Solver {

		int R, G, N, H, MOD = 1_000_000_007;

		int[] tri, gg, memo[];

		void solve(FastScanner s, PrintWriter out) {
			R = s.nextInt();
			G = s.nextInt();
			N = R + G;
			H = (int) Math.floor((-1 + Math.sqrt(1 + (N << 3))) / 2);
			tri = new int[H + 1];
			gg = new int[G + 1];
			for (int i = 1; i <= H; i++)
				tri[i] = R - ((i * i + i) >> 1);
			for (int i = 0; i <= G; i++)
				gg[i] = G - i;
			int[] cur = new int[G + 1], prev = new int[G + 1], temp;
			Arrays.fill(prev, 1);
			for (int row = H; row >= 1; row--) {
				for (int green = G; green >= 0; green--) {
					cur[green] = 0;
					int gl = gg[green], rl = tri[row - 1] + green;
					if (gl >= row)
						cur[green] += prev[green + row];
					if (rl >= row)
						cur[green] += prev[green];
					if (cur[green] >= MOD)
						cur[green] %= MOD;
				}
				temp = cur;
				cur = prev;
				prev = temp;
			}
			out.println(prev[0]);
		}

	}

	public static void main(String[] args) {
		FastScanner s = new FastScanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		Solver solver = new Solver();
		solver.solve(s, out);

		out.close();
	}

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

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

		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++];
		}

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

		boolean isEndline(int c) {
			return c == '\n' || c == '\r' || c == -1;
		}

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

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

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

		public String next() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public String nextLine() {
			int c = read();
			while (isEndline(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isEndline(c));
			return res.toString();
		}

		// Jacob Garbage

		public int[] nextIntArray(int N) {
			int[] ret = new int[N];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextInt();
			return ret;
		}

		public long[] nextLongArray(int N) {
			long[] ret = new long[N];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextLong();
			return ret;
		}

		public int[][] next2DIntArray(int N, int M) {
			int[][] ret = new int[N][];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextIntArray(M);
			return ret;
		}

		public double[] nextDoubleArray(int N) {
			double[] ret = new double[N];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextDouble();
			return ret;
		}

		public double[][] next2DDoubleArray(int N, int M) {
			double[][] ret = new double[N][];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextDoubleArray(M);
			return ret;
		}

	}

}

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

public class RedGreenTowers {

	static class Solver {

		int R, G, N, H, MOD = 1_000_000_007;

		int tri[], memo[][];

		void solve(FastScanner s, PrintWriter out) {
			R = s.nextInt();
			G = s.nextInt();
			N = R + G;
			H = (int) Math.floor((-1 + Math.sqrt(1 + (N << 3))) / 2);
			tri = new int[H + 1];
			for (int i = 1; i <= H; i++)
				tri[i] = (i * i + i) >> 1;
			int[] cur = new int[G + 1], prev = new int[G + 1];
			Arrays.fill(prev, 1);
			for (int row = H; row >= 1; row--) {
				for (int green = G; green >= 0; green--) {
					int gl = G - green, rl = R - tri[row - 1] + green;
					if (gl >= row)
						cur[green] += prev[green + row];
					if (rl >= row)
						cur[green] += prev[green];
				}
				prev = cur.clone();
				Arrays.fill(cur, 0);
			}
			out.println(prev[0]);
		}

	}

	public static void main(String[] args) {
		FastScanner s = new FastScanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		Solver solver = new Solver();
		solver.solve(s, out);

		out.close();
	}

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

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

		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++];
		}

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

		boolean isEndline(int c) {
			return c == '\n' || c == '\r' || c == -1;
		}

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

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

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

		public String next() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public String nextLine() {
			int c = read();
			while (isEndline(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isEndline(c));
			return res.toString();
		}

		// Jacob Garbage

		public int[] nextIntArray(int N) {
			int[] ret = new int[N];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextInt();
			return ret;
		}

		public long[] nextLongArray(int N) {
			long[] ret = new long[N];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextLong();
			return ret;
		}

		public int[][] next2DIntArray(int N, int M) {
			int[][] ret = new int[N][];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextIntArray(M);
			return ret;
		}

		public double[] nextDoubleArray(int N) {
			double[] ret = new double[N];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextDouble();
			return ret;
		}

		public double[][] next2DDoubleArray(int N, int M) {
			double[][] ret = new double[N][];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextDoubleArray(M);
			return ret;
		}

	}

}

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

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);
        TaskD solver = new TaskD();
        solver.solve(in, out);
        out.close();
    }
}

class TaskD {

    private int MAXN = 200000;

    private long DP[][] = new long[2][MAXN+1];

    private long MOD = (long) (1e9 + 7);

    void solve(InputReader in, OutputWriter out) {
        long start = System.currentTimeMillis();

        int red = in.nextInt();
        int green = in.nextInt();
        int height = getMaxHeight(red, green);

        DP[0][0] = 1;
        for(int h=1;h<=height;h++) {
            for(int r=0;r<=red;r++) {
                DP[h&1][r] = 0;
                if(r >= h) {
                    DP[h&1][r] += DP[(h-1)&1][r-h];
                    if(DP[h&1][r] >= MOD) DP[h&1][r] -= MOD;
                }
                int rest = getNumberOfBlocks(h) - r;
                if(green >= rest) {
                    DP[h&1][r] += DP[(h-1)&1][r];
                    if(DP[h&1][r] >= MOD) DP[h&1][r] -= MOD;
                }
            }
        }
        long result = 0;
        for(int i=0;i<=red;i++) {
            result += (DP[height&1][i]);
            if(result >= MOD) result -= MOD;
        }
        out.printLine(result);

        long end = System.currentTimeMillis();
        out.printLine((end-start));
    }

    private int getMaxHeight(int red, int green) {
        int h = 1;
        while(true) {
            if(red + green < getNumberOfBlocks(h)) break;
            h++;
        }
        return (h-1);
    }

    private int getNumberOfBlocks(int height) {
        return ((height) * (height + 1)) / 2;
    }

}
class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;
    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream), 32768);
        tokenizer = null;
    }
    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }
    public boolean hasNext() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                String line = reader.readLine();
                if ( line == null ) {
                    return false;
                }
                tokenizer = new StringTokenizer(line);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return true;
    }
    public int nextInt() {
        return Integer.parseInt(next());
    }
    public long nextLong() {
        return Long.parseLong(next());
    }
    public double nextDouble() { return Double.parseDouble(next());}
}
class OutputWriter {
    private final PrintWriter writer;
    public OutputWriter(OutputStream outputStream) {
        writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
    }
    public OutputWriter(Writer writer) {
        this.writer = new PrintWriter(writer);
    }
    public void print(Object... objects) {
        for (int i = 0; i < objects.length; i++) {
            if ( i != 0 ) {
                writer.print(' ');
            }
            writer.print(objects[i]);
        }
    }
    public void printLine(Object... objects) {
        print(objects);
        writer.println();
    }
    public void close() {
        writer.close();
    }
}

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

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */

public class tower {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Task solver = new Task();
        solver.solve(1, in, out);
        out.close();
    }
}

class Task {
    static final int MOD = (int) (1e9 + 7);

    public long sum(long n) {
        return n * (n + 1) / 2;
    }

    int[][] dp;

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        // type the code here
        int r = in.nextInt();
        int g = in.nextInt();
        int tot = r + g;
        int lef = 1, rig = 1000;
        while(lef < rig) {
            int mid = (lef + rig) >> 1;
            if(sum(mid) < (long) tot) lef = mid + 1;
            else rig = mid;
        }
        //out.println(sum(lef) + " "  + tot);
        if(sum(lef) != tot) {
            out.println(0);
            return;
        }
        r = Math.min(r, g);

        dp = new int[lef + 2][r + 2];
        dp[0][0] = 1;
        for(int i = 1; i <= lef; i++) {
            for(int j = 0; j <= r; j++) {
                dp[i][j] = dp[i - 1][j];
                if(j - i >= 0) dp[i][j] += dp[i - 1][j - i];
                if(dp[i][j] >= MOD)
                    dp[i][j] -= MOD;
            }
        }
        /*
        for(int i = 1; i <= lef; i++) {
            for(int j = 1; j <= r; j++) {
                out.print(dp[i][j] + " ");
            }
            out.println();
        } */
        out.println(dp[lef][r]);
    }
}

class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;

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

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

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

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

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

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

public class D {

	static StringBuilder st = new StringBuilder();
	static final int MOD = (int)1e9 + 7 ;

	static int add(int x , int y)
	{
		int s = x + y ;
		if(s >= MOD)
			return s - MOD ;
		return s ;
	}

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

		int r = sc.nextInt() , g = sc.nextInt() , h = getLevels(r+g);

		int [][] dp = new int [2][g+1];

		Arrays.fill(dp[h & 1], 1);

		for(int level = h - 1 ; level >= 0 ; level --)
			for(int green = g , red =  r  + g - sum(level) - green ; green >= 0 ; green -- , red = r  + g - sum(level) - green)
			{
				int ans = 0 ;

				if(red - level - 1 >= 0)
					ans = add(ans , dp[(level & 1)^1][green]) ;

				if(green - level - 1 >= 0 )
					ans= add(ans, dp[(level & 1)^1][green - level - 1]);

				dp[level&1][green] = ans ;
			}

		out.println(dp[0][g]);

		out.flush();
		out.close();

	}
	static int getLevels(int total)
	{
		int start = 1 , end = 500 , ans = 1;

		while(start <= end)
		{
			int n = (start + end) >> 1 ;

			if(sum(n) <= total)
			{
				ans = n ;
				start = n + 1 ;
			}
			else
				end = n - 1 ;
		}

		return ans ;

	}

	static int sum(int x)
	{
		return (x * (x + 1)) >> 1 ;
	}

	static class Scanner {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;

		Scanner() {
		}

		Scanner(String path) throws Exception {
			br = new BufferedReader(new FileReader(path));
		}

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

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

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

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

	static void shuffle(int[] a) {
		int n = a.length;
		for (int i = 0; i < n; i++) {
			int r = i + (int) (Math.random() * (n - i));
			int tmp = a[i];
			a[i] = a[r];
			a[r] = tmp;
		}
	}

	static void shuffle(char[] a) {
		int n = a.length;
		for (int i = 0; i < n; i++) {
			int r = i + (int) (Math.random() * (n - i));
			char tmp = a[i];
			a[i] = a[r];
			a[r] = tmp;
		}
	}

	static void shuffle(long[] a) {
		int n = a.length;
		for (int i = 0; i < n; i++) {
			int r = i + (int) (Math.random() * (n - i));
			long tmp = a[i];
			a[i] = a[r];
			a[r] = tmp;
		}
	}

	private static boolean oj = System.getProperty("ONLINE_JUDGE") != null;

	private static void tr(Object... o) {
		if (!oj)
			System.out.println(Arrays.deepToString(o));
	}

}

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

public class D_RedGreenTowers {

	static int M = (int) (2 * Math.pow(10, 5)) + 1, N = 633;
	static int mod = (int) (1e9 + 7);
	static int R, G, H;
	static int dp[][] = new int[2][M];

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

		R = sc.nextInt(); G = sc.nextInt();
		int total = R + G;
		H = 1; total -= 1;
		int i = 2;
		while(total >= i) {
			total -= i;
			i++; H++;
		}
		out.println(solve());

		out.flush();
		out.close();
	}

//	private static int solve(int level, int r, int g) {
//		if(level == H + 1) return 1;
//		if(r < level && g < level) return 0;
//		if(memo[level][r] != -1) return memo[level][r];
//
//		int ways = 0;
//		if(g >= level)
//			ways += solve(level + 1, r, g - level);
//		if(r >= level)
//			ways += solve(level + 1, r - level, g);
//		return memo[level][r] = ways % mod;
//	}

	private static int blocks(int level) {
		return (level * (level + 1)) / 2;
	}

	private static int solve() {
		dp[0][R] = 1; int total = R + G;
		int curr = 0;
		for(int i = 0; i < H; ++i) {
			for(int reds = R; reds >= 0; reds--) {
				int greens = total - blocks(i) - reds;
				if(dp[curr][reds] != 0) {
					if(reds >= (i + 1))
						dp[1 - curr][reds - (i + 1)] = (dp[1 - curr][reds - (i + 1)] + dp[curr][reds]) % mod;
					if(greens >= (i + 1)) dp[1 - curr][reds] = (dp[curr][reds] + dp[1 - curr][reds]) % mod;
				}
				dp[curr][reds] = 0;
			}
			curr = 1 - curr;
		}
		int res = 0;
		for(int i = 0; i <= R; ++i) res += dp[curr][i];
		return res;
	}

	static class Scanner{
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}

		public Scanner(FileReader r){	br = new BufferedReader(r);}

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

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

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

		public String nextLine() throws IOException {return br.readLine();}

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

		public boolean ready() throws IOException {return br.ready();}
	}
}

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

public class Main {

	static int M = (int) (2 * Math.pow(10, 5)) + 1, N = 633;
	static int mod = (int) (1e9 + 7);
	static int R, G, H;
	static int dp[][] = new int[2][M];

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

		R = sc.nextInt(); G = sc.nextInt();
		int total = R + G;
		H = 1; total -= 1;
		int i = 2;
		while(total >= i) {
			total -= i;
			i++; H++;
		}
		out.println(solve());

		out.flush();
		out.close();
	}

//	private static int solve(int level, int r, int g) {
//		if(level == H + 1) return 1;
//		if(r < level && g < level) return 0;
//		if(memo[level][r] != -1) return memo[level][r];
//
//		int ways = 0;
//		if(g >= level)
//			ways += solve(level + 1, r, g - level);
//		if(r >= level)
//			ways += solve(level + 1, r - level, g);
//		return memo[level][r] = ways % mod;
//	}

	private static int blocks(int level) {
		return (level * (level + 1)) / 2;
	}

	private static int solve() {
		dp[0][R] = 1; int total = R + G;
		int curr = 0;
		for(int i = 0; i < H; ++i) {
			for(int reds = R; reds >= 0; reds--) {
				int greens = total - blocks(i) - reds;
				if(dp[curr][reds] != 0) {
					if(reds >= (i + 1)) dp[1 - curr][reds - (i + 1)] += dp[curr][reds];
					if(greens >= (i + 1)) dp[1 - curr][reds] += dp[curr][reds];
				}
				dp[curr][reds] = 0;
			}
			curr = 1 - curr;
		}
		int res = 0;
		for(int i = 0; i <= R; ++i) res += dp[curr][i];
		return res;
	}

	static class Scanner{
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}

		public Scanner(FileReader r){	br = new BufferedReader(r);}

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

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

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

		public String nextLine() throws IOException {return br.readLine();}

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

		public boolean ready() throws IOException {return br.ready();}
	}
}

import java.util.*;
public class B {
	public static void main(String args[]) {
		Scanner sc = new Scanner(System.in);
		int r = sc.nextInt();
		int g = sc.nextInt();
		int mod = 1000000007;
		int[] table = new int[r+1];
		int total = 0;
		int ans = 0;
		table[0] = 1; // 0 level
		for(int i=1; i<=700; i++) {
			total += i;
			for(int j = r; j>=0; j--) {
				int fillg = total - j <=g ? table[j] : 0;
				int fillr = j >= i ? table[j-i] : 0;
				table[j] = (fillg + fillr)%mod;
//				if(total - j <= g) { // fill with g
//					table[i%2][j] = (table[i%2][j] + table[1-i%2][j])%mod;
//				}
//				if(j>=i) { // fill with r
//					table[i%2][j] = (table[i%2][j] + table[1-i%2][j-i])%mod;
//				}
			}
			int temp = 0;
			for(int j=0; j<=r; j++) {
				temp = (temp + table[j])%mod;
			}
//			if(temp > 0) { // have feasible way to make the height
//				ans = temp;
//			}
			if(temp<=0)
				break;
			ans = temp;
		}
		System.out.println(ans);
	}
}

import java.util.Arrays;
import java.util.Scanner;

public class RedGreenTowers
{
	static int r, g;
	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		r = sc.nextInt();
		g = sc.nextInt();
		int h = bs(0, 1000);
		int total = ((h)*(h+1))/2;
		int[][] dp = new int[2][200010];
		int p = 0;
		Arrays.fill(dp[p], 1);
		for (int lvl = h-1; lvl >= 0; lvl--)
		{
			p = 1-p;
			for (int green = 0; green <= g; green++)
			{
				dp[p][green] = 0;
				int cur = h-lvl;
				if(green-cur >= 0)
					dp[p][green] += dp[1-p][green-cur];
				int red = r-(total - (((cur)*(cur+1))/2) - (g-green));
				if(red-cur >= 0 && red <= r)
					dp[p][green] += dp[1-p][green];
			}
		}
		System.out.println(dp[p][g]);
	}

	static int bs(int st, int en)
	{
		if(st == en)
			return st;
		int mid = st + (en-st+1)/2;
		if(can(mid))
			return bs(mid, en);
		return bs(st, mid-1);
	}
	private static boolean can(int mid)
	{
		int[] tmp = {r,g};
		int lvl = mid;

		while(true)
		{
			if(lvl == 0)
				return true;
			int l = 0;
			if(tmp[1] > tmp[0])
				l = 1;
			if(tmp[l] < lvl)
				return false;
			tmp[l]-=lvl;
			lvl--;
		}
	}

	// dp(currentLevel, green) = dp(lvl+1, green-lvl) + dp(lvl+1, green)
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.io.PrintWriter;
import java.util.Arrays;
public class D478
{
    static class Scanner
    {
        BufferedReader br;
        StringTokenizer tk=new StringTokenizer("");
        public Scanner(InputStream is)
        {
            br=new BufferedReader(new InputStreamReader(is));
        }
        public int nextInt() throws IOException
        {
            if(tk.hasMoreTokens())
                return Integer.parseInt(tk.nextToken());
            tk=new StringTokenizer(br.readLine());
            return nextInt();
        }
        public long nextLong() throws IOException
        {
            if(tk.hasMoreTokens())
                return Long.parseLong(tk.nextToken());
            tk=new StringTokenizer(br.readLine());
            return nextLong();
        }
        public String next() throws IOException
        {
            if(tk.hasMoreTokens())
                return (tk.nextToken());
            tk=new StringTokenizer(br.readLine());
            return next();
        }
        public String nextLine() throws IOException
        {
            tk=new StringTokenizer("");
            return br.readLine();
        }
        public double nextDouble() throws IOException
        {
            if(tk.hasMoreTokens())
                return Double.parseDouble(tk.nextToken());
            tk=new StringTokenizer(br.readLine());
            return nextDouble();
        }
        public char nextChar() throws IOException
        {
            if(tk.hasMoreTokens())
                return (tk.nextToken().charAt(0));
            tk=new StringTokenizer(br.readLine());
            return nextChar();
        }
        public int[] nextIntArray(int n) throws IOException
        {
            int a[]=new int[n];
            for(int i=0;i<n;i++)
                a[i]=nextInt();
            return a;
        }
        public long[] nextLongArray(int n) throws IOException
        {
            long a[]=new long[n];
            for(int i=0;i<n;i++)
                a[i]=nextLong();
            return a;
        }
        public int[] nextIntArrayOneBased(int n) throws IOException
        {
            int a[]=new int[n+1];
            for(int i=1;i<=n;i++)
                a[i]=nextInt();
            return a;
        }
        public long[] nextLongArrayOneBased(int n) throws IOException
        {
            long a[]=new long[n+1];
            for(int i=1;i<=n;i++)
                a[i]=nextLong();
            return a;
        }

    }

    public static void main(String args[]) throws IOException
    {

        Scanner in=new Scanner(System.in);
        PrintWriter out=new PrintWriter(System.out);
        int r=in.nextInt();
        int g=in.nextInt();
        long mod=1000000007;
        int max=0;
        int lo=0,hi=10000;
        while(lo<=hi)
        {
            int mid=(lo+hi)/2;
            int a[]=new int[]{r,g};
            for(int i=1;i<=mid;i++)
            {
                Arrays.sort(a);
                a[1]-=i;
            }
            if(a[0]<0||a[1]<0)
            {
                hi=mid-1;
            }
            else
            {
                lo=mid+1;
                max=Math.max(max,mid);
            }
        }
        long ans=0;
        long dp[]=new long[r+1];
        dp[0]=1;
        for(int i=0;i<max;i++)
            for(int j=r;j>=0;j--)
            {
                int b=j+i+1;
                if(b<=r)
                {
                    dp[b]=(dp[b]+dp[j]);
                    if(dp[b]>=mod)
                        dp[b]-=mod;
                }
            }
        max*=(max+1);
        max/=2;
        max-=g;
        for(int i=Math.max(0,max);i<=r;i++)
            ans=(ans+dp[i])%mod;
        out.println(ans);
        out.close();
    }

}

import java.io.*;
import java.util.*;
/*
 * 	Heart beats fast
 * 		Colors and promises
 * 			How to be brave
 * 				How can I love when I am afraid to fall...
 */
//read the question correctly (is y a vowel? what are the exact constraints?)
//look out for SPECIAL CASES (n=1?) and overflow (ll vs int?)
public class Main
{
	public static void main(String[] args)
	{
		int red=ni(),green=ni();
		int r=Math.min(red, green),g=Math.max(red, green);
		int tr=(int)((-1+Math.sqrt(1+8*r))/2);
		int sur=r-(tr*(tr+1))/2;
		int rem=g;
		int h=tr;
		if(sur>0)
		{
			h++;
			rem-=sur;
		}
		while(rem>h)
			rem-=++h;
		int dp[][]=new int[2][r+1];
		dp[0][r]=1;
		int[]te;
		for(int i=0; i<h; i++)
		{
		    int tem=Math.min(r,g-1-i+r-(i*(i+1))/2);
			for(int j=0; j<=tem; j++)
				dp[1][j]=dp[0][j];
			for(int j=i+1; j<=r; j++)
				dp[1][j-i-1]=(dp[1][j-i-1]+dp[0][j])%mod;
			te=dp[0];
			dp[0]=dp[1];
			dp[1]=te;
 			Arrays.fill(dp[1],0);
		}
		long ans=0;
		for(int i:dp[0])
			ans=(ans+i);
		pr(ans%mod);
		System.out.print(output);
	}
	///////////////////////////////////////////
	///////////////////////////////////////////
	///template from here
	static final int mod=1000000007;
	static final double eps=1e-8;
	static final long inf=100000000000000000L;
	static Reader in=new Reader();
	static StringBuilder output=new StringBuilder();
	static Random rn=new Random();
	//output functions////////////////
	static void pr(Object a){output.append(a+"\n");}
	static void pr(){output.append("\n");}
	static void p(Object a){output.append(a);}
	static void pra(int[]a){for(int i:a)output.append(i+" ");output.append("\n");}
	static void pra(long[]a){for(long i:a)output.append(i+" ");output.append("\n");}
	static void pra(String[]a){for(String i:a)output.append(i+" ");output.append("\n");}
	static void pra(double[]a){for(double i:a)output.append(i+" ");output.append("\n");}
	static void sop(Object a){System.out.println(a);}
	static void flush(){System.out.println(output);output=new StringBuilder();}
	//////////////////////////////////
	//input functions/////////////////
	static int ni(){return in.nextInt();}
	static long nl(){return Long.parseLong(in.next());}
	static String ns(){return in.next();}
	static double nd(){return Double.parseDouble(in.next());}
	static int[] nia(int n){int a[]=new int[n];for(int i=0; i<n; i++)a[i]=ni();return a;}
	static int[] pnia(int n){int a[]=new int[n+1];for(int i=1; i<=n; i++)a[i]=ni();return a;}
	static long[] nla(int n){long a[]=new long[n];for(int i=0; i<n; i++)a[i]=nl();return a;}
	static String[] nsa(int n){String a[]=new String[n];for(int i=0; i<n; i++)a[i]=ns();return a;}
	static double[] nda(int n){double a[]=new double[n];for(int i=0; i<n; i++)a[i]=nd();return a;}
	//////////////////////////////////
	//some utility functions
	static void exit(){System.exit(0);}
	static void psort(int[][] a)
	{
		Arrays.sort(a, new Comparator<int[]>()
		{
			@Override
			public int compare(int[]a,int[]b)
			{
				if(a[0]>b[0])
					return 1;
				else if(b[0]>a[0])
					return -1;
				return 0;
			}
		});
	}
	static String pr(String a, long b)
	{
		String c="";
		while(b>0)
		{
			if(b%2==1)
				c=c.concat(a);
			a=a.concat(a);
			b>>=1;
		}
		return c;
	}
	static long powm(long a, long b, long m)
	{
		long an=1;
		long c=a;
		while(b>0)
		{
			if(b%2==1)
				an=(an*c)%m;
			c=(c*c)%m;
			b>>=1;
		}
		return an;
	}
	static int gcd(int a, int b)
	{
		if(b==0)
			return a;
		else
			return gcd(b, a%b);
	}
	/////////////////////////
	static class Reader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;
        public Reader() {
            reader = new BufferedReader(new InputStreamReader(System.in), 32768);
            tokenizer = null;
        }
        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }
        public long nextLong() {
        	return Long.parseLong(next());
        }
        public double nextDouble() {
        	return Double.parseDouble(next());
        }
    }
}

import java.io.*;
import java.util.*;
/*
 * 	Heart beats fast
 * 		Colors and promises
 * 			How to be brave
 * 				How can I love when I am afraid to fall...
 */
//read the question correctly (is y a vowel? what are the exact constraints?)
//look out for SPECIAL CASES (n=1?) and overflow (ll vs int?)
public class Main
{
	public static void main(String[] args)
	{
		int red=ni(),green=ni();
		int r=Math.min(red, green),g=Math.max(red, green);
		int tr=(int)((-1+Math.sqrt(1+8*r))/2);
		int sur=r-(tr*(tr+1))/2;
		int rem=g;
		int h=tr;
		if(sur>0)
		{
			h++;
			rem-=sur;
		}
		while(rem>h)
			rem-=++h;
		int dp[][]=new int[2][r+1];
		dp[0][r]=1;
		int[]te;
		for(int i=0; i<h; i++)
		{
		    int tem=Math.min(r,g-1-i+r-(i*(i+1))/2);
			for(int j=0; j<=tem; j++)
				dp[1][j]=dp[0][j];
			for(int j=i+1; j<=r; j++)
				dp[1][j-i-1]=(dp[1][j-i-1]+dp[0][j])%mod;
			long sum=0;
			for(int j=0; j<=r; j++)
				sum+=dp[1][j];
			if(sum==0)
				break;
			te=dp[0];
			dp[0]=dp[1];
			dp[1]=te;
 			Arrays.fill(dp[1],0);
		}
		long ans=0;
		for(int i:dp[0])
			ans=(ans+i);
		pr(ans%mod);
		System.out.print(output);
	}
	///////////////////////////////////////////
	///////////////////////////////////////////
	///template from here
	static final int mod=1000000007;
	static final double eps=1e-8;
	static final long inf=100000000000000000L;
	static Reader in=new Reader();
	static StringBuilder output=new StringBuilder();
	static Random rn=new Random();
	//output functions////////////////
	static void pr(Object a){output.append(a+"\n");}
	static void pr(){output.append("\n");}
	static void p(Object a){output.append(a);}
	static void pra(int[]a){for(int i:a)output.append(i+" ");output.append("\n");}
	static void pra(long[]a){for(long i:a)output.append(i+" ");output.append("\n");}
	static void pra(String[]a){for(String i:a)output.append(i+" ");output.append("\n");}
	static void pra(double[]a){for(double i:a)output.append(i+" ");output.append("\n");}
	static void sop(Object a){System.out.println(a);}
	static void flush(){System.out.println(output);output=new StringBuilder();}
	//////////////////////////////////
	//input functions/////////////////
	static int ni(){return in.nextInt();}
	static long nl(){return Long.parseLong(in.next());}
	static String ns(){return in.next();}
	static double nd(){return Double.parseDouble(in.next());}
	static int[] nia(int n){int a[]=new int[n];for(int i=0; i<n; i++)a[i]=ni();return a;}
	static int[] pnia(int n){int a[]=new int[n+1];for(int i=1; i<=n; i++)a[i]=ni();return a;}
	static long[] nla(int n){long a[]=new long[n];for(int i=0; i<n; i++)a[i]=nl();return a;}
	static String[] nsa(int n){String a[]=new String[n];for(int i=0; i<n; i++)a[i]=ns();return a;}
	static double[] nda(int n){double a[]=new double[n];for(int i=0; i<n; i++)a[i]=nd();return a;}
	//////////////////////////////////
	//some utility functions
	static void exit(){System.exit(0);}
	static void psort(int[][] a)
	{
		Arrays.sort(a, new Comparator<int[]>()
		{
			@Override
			public int compare(int[]a,int[]b)
			{
				if(a[0]>b[0])
					return 1;
				else if(b[0]>a[0])
					return -1;
				return 0;
			}
		});
	}
	static String pr(String a, long b)
	{
		String c="";
		while(b>0)
		{
			if(b%2==1)
				c=c.concat(a);
			a=a.concat(a);
			b>>=1;
		}
		return c;
	}
	static long powm(long a, long b, long m)
	{
		long an=1;
		long c=a;
		while(b>0)
		{
			if(b%2==1)
				an=(an*c)%m;
			c=(c*c)%m;
			b>>=1;
		}
		return an;
	}
	static int gcd(int a, int b)
	{
		if(b==0)
			return a;
		else
			return gcd(b, a%b);
	}
	/////////////////////////
	static class Reader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;
        public Reader() {
            reader = new BufferedReader(new InputStreamReader(System.in), 32768);
            tokenizer = null;
        }
        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }
        public long nextLong() {
        	return Long.parseLong(next());
        }
        public double nextDouble() {
        	return Double.parseDouble(next());
        }
    }
}

import java.io.*;
import java.util.*;
/*
 * 	Heart beats fast
 * 		Colors and promises
 * 			How to be brave
 * 				How can I love when I am afraid to fall...
 */
//read the question correctly (is y a vowel? what are the exact constraints?)
//look out for SPECIAL CASES (n=1?) and overflow (ll vs int?)
public class Main
{
	public static void main(String[] args)
	{
		int red=ni(),green=ni();
		int r=Math.min(red, green),g=Math.max(red, green);
		int dp[][]=new int[2][r+1];
		dp[0][r]=1;
		int[]te;
		int h=(int)Math.sqrt(1+8*(r+g))/2;
		for(int i=0; i<h; i++)
		{
		    int tem=Math.min(r,g-1-i+r-(i*(i+1))/2);
			for(int j=0; j<=tem; j++)
				dp[1][j]=dp[0][j];
			for(int j=i+1; j<=r; j++)
				dp[1][j-i-1]=(dp[1][j-i-1]+dp[0][j])%mod;
			te=dp[0];
			dp[0]=dp[1];
			dp[1]=te;
 			Arrays.fill(dp[1],0);
		}
		long ans=0;
		for(int i:dp[0])
			ans=(ans+i);
		pr(ans%mod);
		System.out.print(output);
	}
	///////////////////////////////////////////
	///////////////////////////////////////////
	///template from here
	static final int mod=1000000007;
	static final double eps=1e-8;
	static final long inf=100000000000000000L;
	static Reader in=new Reader();
	static StringBuilder output=new StringBuilder();
	static Random rn=new Random();
	//output functions////////////////
	static void pr(Object a){output.append(a+"\n");}
	static void pr(){output.append("\n");}
	static void p(Object a){output.append(a);}
	static void pra(int[]a){for(int i:a)output.append(i+" ");output.append("\n");}
	static void pra(long[]a){for(long i:a)output.append(i+" ");output.append("\n");}
	static void pra(String[]a){for(String i:a)output.append(i+" ");output.append("\n");}
	static void pra(double[]a){for(double i:a)output.append(i+" ");output.append("\n");}
	static void sop(Object a){System.out.println(a);}
	static void flush(){System.out.println(output);output=new StringBuilder();}
	//////////////////////////////////
	//input functions/////////////////
	static int ni(){return in.nextInt();}
	static long nl(){return Long.parseLong(in.next());}
	static String ns(){return in.next();}
	static double nd(){return Double.parseDouble(in.next());}
	static int[] nia(int n){int a[]=new int[n];for(int i=0; i<n; i++)a[i]=ni();return a;}
	static int[] pnia(int n){int a[]=new int[n+1];for(int i=1; i<=n; i++)a[i]=ni();return a;}
	static long[] nla(int n){long a[]=new long[n];for(int i=0; i<n; i++)a[i]=nl();return a;}
	static String[] nsa(int n){String a[]=new String[n];for(int i=0; i<n; i++)a[i]=ns();return a;}
	static double[] nda(int n){double a[]=new double[n];for(int i=0; i<n; i++)a[i]=nd();return a;}
	//////////////////////////////////
	//some utility functions
	static void exit(){System.exit(0);}
	static void psort(int[][] a)
	{
		Arrays.sort(a, new Comparator<int[]>()
		{
			@Override
			public int compare(int[]a,int[]b)
			{
				if(a[0]>b[0])
					return 1;
				else if(b[0]>a[0])
					return -1;
				return 0;
			}
		});
	}
	static String pr(String a, long b)
	{
		String c="";
		while(b>0)
		{
			if(b%2==1)
				c=c.concat(a);
			a=a.concat(a);
			b>>=1;
		}
		return c;
	}
	static long powm(long a, long b, long m)
	{
		long an=1;
		long c=a;
		while(b>0)
		{
			if(b%2==1)
				an=(an*c)%m;
			c=(c*c)%m;
			b>>=1;
		}
		return an;
	}
	static int gcd(int a, int b)
	{
		if(b==0)
			return a;
		else
			return gcd(b, a%b);
	}
	/////////////////////////
	static class Reader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;
        public Reader() {
            reader = new BufferedReader(new InputStreamReader(System.in), 32768);
            tokenizer = null;
        }
        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }
        public long nextLong() {
        	return Long.parseLong(next());
        }
        public double nextDouble() {
        	return Double.parseDouble(next());
        }
    }
}

import java.io.*;
import java.util.*;
/*
 * 	Heart beats fast
 * 		Colors and promises
 * 			How to be brave
 * 				How can I love when I am afraid to fall...
 */
//read the question correctly (is y a vowel? what are the exact constraints?)
//look out for SPECIAL CASES (n=1?) and overflow (ll vs int?)
public class Main
{
	public static void main(String[] args)
	{
		int red=ni(),green=ni();
		int r=Math.min(red, green),g=Math.max(red, green);
		int tr=(int)((-1+Math.sqrt(1+8*r))/2);
		int sur=r-(tr*(tr+1))/2;
		int rem=g;
		int h=tr;
		if(sur>0)
		{
			h++;
			rem-=sur;
		}
		while(rem>h)
			rem-=++h;
		int dp[][]=new int[2][r+1];
		dp[0][r]=1;
		for(int i=0; i<h; i++)
		{
			for(int j=0; j<=i&&j<=r; j++)
			{
				if((i*(i+1))/2-r+j+i+1<=g)
					dp[1][j]=(dp[1][j]+dp[0][j])%mod;
			}
			for(int j=i+1; j<=r; j++)
			{
				if((i*(i+1))/2-r+j+i+1<=g)
					dp[1][j]=(dp[1][j]+dp[0][j])%mod;
				dp[1][j-i-1]=(dp[1][j-i-1]+dp[0][j])%mod;
			}
			dp[1]=dp[0];
			dp[1]=new int[r+1];
		}
		int ans=0;
		for(int i:dp[0])
			ans=(ans+i)%mod;
		pr(ans);
		System.out.print(output);
	}
	///////////////////////////////////////////
	///////////////////////////////////////////
	///template from here
	static final int mod=1000000007;
	static final double eps=1e-8;
	static final long inf=100000000000000000L;
	static Reader in=new Reader();
	static StringBuilder output=new StringBuilder();
	static Random rn=new Random();
	//output functions////////////////
	static void pr(Object a){output.append(a+"\n");}
	static void pr(){output.append("\n");}
	static void p(Object a){output.append(a);}
	static void pra(int[]a){for(int i:a)output.append(i+" ");output.append("\n");}
	static void pra(long[]a){for(long i:a)output.append(i+" ");output.append("\n");}
	static void pra(String[]a){for(String i:a)output.append(i+" ");output.append("\n");}
	static void pra(double[]a){for(double i:a)output.append(i+" ");output.append("\n");}
	static void sop(Object a){System.out.println(a);}
	static void flush(){System.out.println(output);output=new StringBuilder();}
	//////////////////////////////////
	//input functions/////////////////
	static int ni(){return in.nextInt();}
	static long nl(){return Long.parseLong(in.next());}
	static String ns(){return in.next();}
	static double nd(){return Double.parseDouble(in.next());}
	static int[] nia(int n){int a[]=new int[n];for(int i=0; i<n; i++)a[i]=ni();return a;}
	static int[] pnia(int n){int a[]=new int[n+1];for(int i=1; i<=n; i++)a[i]=ni();return a;}
	static long[] nla(int n){long a[]=new long[n];for(int i=0; i<n; i++)a[i]=nl();return a;}
	static String[] nsa(int n){String a[]=new String[n];for(int i=0; i<n; i++)a[i]=ns();return a;}
	static double[] nda(int n){double a[]=new double[n];for(int i=0; i<n; i++)a[i]=nd();return a;}
	//////////////////////////////////
	//some utility functions
	static void exit(){System.exit(0);}
	static void psort(int[][] a)
	{
		Arrays.sort(a, new Comparator<int[]>()
		{
			@Override
			public int compare(int[]a,int[]b)
			{
				if(a[0]>b[0])
					return 1;
				else if(b[0]>a[0])
					return -1;
				return 0;
			}
		});
	}
	static String pr(String a, long b)
	{
		String c="";
		while(b>0)
		{
			if(b%2==1)
				c=c.concat(a);
			a=a.concat(a);
			b>>=1;
		}
		return c;
	}
	static long powm(long a, long b, long m)
	{
		long an=1;
		long c=a;
		while(b>0)
		{
			if(b%2==1)
				an=(an*c)%m;
			c=(c*c)%m;
			b>>=1;
		}
		return an;
	}
	static int gcd(int a, int b)
	{
		if(b==0)
			return a;
		else
			return gcd(b, a%b);
	}
	/////////////////////////
	static class Reader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;
        public Reader() {
            reader = new BufferedReader(new InputStreamReader(System.in), 32768);
            tokenizer = null;
        }
        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }
        public long nextLong() {
        	return Long.parseLong(next());
        }
        public double nextDouble() {
        	return Double.parseDouble(next());
        }
    }
}

import java.util.HashMap;
import java.io.DataInputStream;
import java.io.PrintWriter;
import java.io.FileInputStream;
import java.io.IOException;

public class Redgreentowers
{
	static class Reader
	{
		final private int BUFFER_SIZE = 1 << 16;
		private DataInputStream din;
		private byte[] buffer;
		private int bufferPointer, bytesRead;

		public Reader()
		{
			din = new DataInputStream(System.in);
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}

		public Reader(String file_name) throws IOException
		{
			din = new DataInputStream(new FileInputStream(file_name));
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}

		public String readLine() throws IOException
		{
			byte[] buf = new byte[201]; // line length
			int cnt = 0, c;
			while ((c = read()) != -1)
			{
				if (c == '\n')
					break;
				buf[cnt++] = (byte) c;
			}
			return new String(buf, 0, cnt);
		}

		public int nextInt() throws IOException
		{
			int ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do
			{
				ret = ret * 10 + c - '0';
			} while ((c = read()) >= '0' && c <= '9');

			if (neg)
				return -ret;
			return ret;
		}

		public long nextLong() throws IOException
		{
			long ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do {
				ret = ret * 10 + c - '0';
			}
			while ((c = read()) >= '0' && c <= '9');
			if (neg)
				return -ret;
			return ret;
		}

		public double nextDouble() throws IOException
		{
			double ret = 0, div = 1;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();

			do {
				ret = ret * 10 + c - '0';
			}
			while ((c = read()) >= '0' && c <= '9');

			if (c == '.')
			{
				while ((c = read()) >= '0' && c <= '9')
				{
					ret += (c - '0') / (div *= 10);
				}
			}

			if (neg)
				return -ret;
			return ret;
		}

		private void fillBuffer() throws IOException
		{
			bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
			if (bytesRead == -1)
				buffer[0] = -1;
		}

		private byte read() throws IOException
		{
			if (bufferPointer == bytesRead)
				fillBuffer();
			return buffer[bufferPointer++];
		}

		public void close() throws IOException
		{
			if (din == null)
				return;
			din.close();
		}
	}

        static long mod=(long)(1E+9)+7;
        static HashMap<Integer,pair> hm[][];
        static class pair{
         int l;long val;
         pair(int a,long b){l=a;val=b;}
        }
        static pair rec(int l,int cr,int cg,int put){
         if((put==0&&cr<l)||(put==1&&cg<l))return new pair(0,0);
         if(hm[cr][put].get(l)!=null)return hm[cr][put].get(l);
         int ar=0,ag=-l;if(put==0){ar=-l;ag=0;}
         pair p1=rec(l+1,cr+ar,cg+ag,0);pair p2=rec(l+1,cr+ar,cg+ag,1);
         if(p1.l==p2.l)hm[cr][put].put(l,new pair(p1.l,(p1.val+p2.val)%mod));
         else if(p1.l>p2.l)hm[cr][put].put(l,p1);
         else hm[cr][put].put(l,p2);
         if(hm[cr][put].get(l).val==0)hm[cr][put].put(l,new pair(l,1));
         return hm[cr][put].get(l);
        }
        public static void main(String[] args) throws IOException
	{
		Reader s=new Reader();PrintWriter pw=new PrintWriter(System.out);
                int r=s.nextInt(),g=s.nextInt();
                hm=new HashMap[r+1][2];
                for(int i=0;i<=r;i++){
                 for(int j=0;j<2;j++)hm[i][j]=new HashMap<>();
                }
                pair p1=rec(1,r,g,0);pair p2=rec(1,r,g,1);System.out.println(p1.val+" "+p2.val);
                long ans=0;
                if(p1.l>p2.l)ans=p1.val;
                else if(p1.l<p2.l)ans=p2.val;
                else ans=(p1.val+p2.val)%mod;
                pw.write(ans+"");
		pw.flush();pw.close();
	}
}