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=1000;
        while(lo<=hi)
        {
            int mid=(lo+hi)/2;
            int a[]=new int[]{r,g};
            for(int i=mid;i>0;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.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.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;
    }
}

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

/**
 * ******* 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.*;
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.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.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.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.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.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]);
    }
}

/**
 * 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.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.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.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.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.*;
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.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.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 ************************/

}

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

	}
}

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

	}

}

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

}

// 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.*;

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

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.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.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 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.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.*;

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.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.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.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 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.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.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.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.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 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);

    }
}

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

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

}

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