macro_rules! scan_sub {
    ( $itr:ident, $t:ty ) => {
        let mut buf = String::new();
        let $itr = {
            while buf.trim().len() == 0 {
                buf = String::new();
                std::io::stdin().read_line(&mut buf).unwrap();
            }
            buf.split_whitespace().map(|n| n.parse::<$t>().unwrap())
        };
    };
}

macro_rules! scan {
    ( $x:ident; Vec<$t:ty> ) => {
        scan_sub!(itr, $t);
        let $x = itr.collect::<Vec<_>>();
    };
    ( $( $x:ident ),*; $t:ty ) => {
        scan_sub!(itr, $t);
        let mut itr = itr;
        $(
            let $x = itr.next().unwrap();
        )*
    };
}

#[allow(dead_code)]
mod modint {
    use std::ops;

    const MOD: usize = 1000000007;

    #[derive(Debug, Copy, Clone, PartialEq, Eq)]
    pub struct ModInt {
        val: usize,
    }

    impl ModInt {
        pub fn new(n: usize) -> Self {
            ModInt { val: n % MOD }
        }

        pub fn val(&self) -> usize {
            // 念のためMOD演算
            self.val % MOD
        }

        pub fn _set_val(&mut self, val: usize) {
            self.val = val % MOD;
        }

        pub fn pow_u(&self, mut n: usize) -> Self {
            let mut val = self.val;
            let mut res: usize = 1;
            while n > 0 {
                if n % 2 == 1 {
                    res = (res * val) % MOD;
                }
                val = (val * val) % MOD;
                n /= 2;
            }

            ModInt { val: res }
        }

        pub fn pow(&self, other: Self) -> Self {
            self.pow_u(other.val)
        }

        pub fn inv(&self) -> Self {
            self.pow_u(MOD - 2)
        }
    }

    impl ops::Add for ModInt {
        type Output = Self;

        fn add(self, other: Self) -> Self {
            ModInt {
                val: (self.val + other.val) % MOD,
            }
        }
    }

    impl ops::AddAssign for ModInt {
        fn add_assign(&mut self, other: Self) {
            *self = ModInt {
                val: (self.val + other.val) % MOD,
            };
        }
    }

    impl ops::Mul for ModInt {
        type Output = Self;

        fn mul(self, other: Self) -> Self {
            ModInt {
                val: (self.val * other.val) % MOD,
            }
        }
    }

    impl ops::MulAssign for ModInt {
        fn mul_assign(&mut self, other: Self) {
            *self = ModInt {
                val: (self.val * other.val) % MOD,
            };
        }
    }

    impl ops::Sub for ModInt {
        type Output = Self;

        fn sub(mut self, other: Self) -> Self {
            if self.val < other.val {
                self.val += MOD;
            }
            ModInt {
                val: self.val - other.val % MOD,
            }
        }
    }

    impl ops::SubAssign for ModInt {
        fn sub_assign(&mut self, other: Self) {
            if self.val < other.val {
                self.val += MOD;
            }
            *self = ModInt {
                val: (self.val - other.val) % MOD,
            };
        }
    }

    impl ops::Div for ModInt {
        type Output = Self;

        fn div(self, other: Self) -> Self {
            if other.val == 0 {
                panic!("0 division occured.");
            }

            self * other.inv()
        }
    }

    impl ops::DivAssign for ModInt {
        fn div_assign(&mut self, other: Self) {
            if other.val == 0 {
                panic!("0 division occured.");
            }

            *self *= other.inv();
        }
    }

    pub struct ModCom {
        fac: Vec<usize>,
        finv: Vec<usize>,
    }

    impl ModCom {
        pub fn new(cap: usize) -> Self {
            let mut fac = vec![0; cap];
            let mut finv = vec![0; cap];
            let mut inv = vec![0; cap];
            fac[0] = 1;
            fac[1] = 1;
            finv[0] = 1;
            finv[1] = 1;
            inv[1] = 1;
            for i in 2..cap {
                fac[i] = fac[i - 1] * i % MOD;
                inv[i] = MOD - inv[MOD % i] * (MOD / i) % MOD;
                finv[i] = finv[i - 1] * inv[i] % MOD;
            }

            ModCom {
                fac: fac,
                finv: finv,
            }
        }

        pub fn com(&self, n: usize, k: usize) -> usize {
            if n < k {
                return 0;
            }
            self.fac[n] * (self.finv[k] * self.finv[n - k] % MOD) % MOD
        }
    }
}

fn main() {
    use modint::ModCom;

    scan!(x, y; usize);

    if (x + y) % 3 != 0 {
        println!("0");
        return;
    }

    let t = (x + y) / 3;
    let n = y - t;
    // let _m = x - t;

    let c = ModCom::new(t + 1);
    println!("{}", c.com(t, n));
}


Measured memory_bytes: 22780