pub mod solution {

use std::cmp::min;
use crate::io::input::Input;
use crate::io::output::output;
use crate::{out, out_line};

fn solve(input: &mut Input, _test_case: usize) {
    let (n, k) = input.read();
    let mut ans = 0;
    let mut fact = vec![0; n + 1];
    let mut inv = vec![0; n + 1];
    let mut invfact = vec![0; n + 1];
    inv[1] = 1;
    for i in 2..=n {
        inv[i] = mul(inv[(MOD % i as i32) as usize], MOD - MOD / i as i32);
    }
    fact[0] = 1;
    invfact[0] = 1;
    for i in 1..=n {
        fact[i] = mul(fact[i - 1], i as i32);
        invfact[i] = mul(invfact[i - 1], inv[i]);
    }
    for i in 0..=min(k, n) {
        add(&mut ans, c(n, i, &fact, &invfact));
    }
    out_line!(ans);
}

fn c(n: usize, k: usize, fact: &Vec<i32>, invfact: &Vec<i32>) -> i32 {
    mul(fact[n], mul(invfact[k], invfact[n - k]))
}

fn add(a: &mut i32, b: i32) {
    *a += b;
    if *a >= MOD {
        *a -= MOD;
    }
}

const MOD: i32 = 1000000007;

fn mul(a: i32, b: i32) -> i32 {
    (a as i64 * b as i64 % MOD as i64) as i32
}

pub(crate) fn run(mut input: Input) -> bool {
    solve(&mut input, 1);
    output().flush();
    input.skip_whitespace();
    !input.peek().is_some()
}

}
pub mod io {
pub mod input {
use std::fmt::Debug;
use std::io::Read;
use std::marker::PhantomData;
use std::str::FromStr;

pub struct Input<'s> {
    input: &'s mut dyn Read,
    buf: Vec<u8>,
    at: usize,
    buf_read: usize,
}

impl<'s> Input<'s> {
    const DEFAULT_BUF_SIZE: usize = 4096;

    pub fn new(input: &'s mut dyn Read) -> Self {
        Self {
            input,
            buf: vec![0; Self::DEFAULT_BUF_SIZE],
            at: 0,
            buf_read: 0,
        }
    }

    pub fn new_with_size(input: &'s mut dyn Read, buf_size: usize) -> Self {
        Self {
            input,
            buf: vec![0; buf_size],
            at: 0,
            buf_read: 0,
        }
    }

    pub fn get(&mut self) -> Option<u8> {
        if self.refill_buffer() {
            let res = self.buf[self.at];
            self.at += 1;
            Some(res)
        } else {
            None
        }
    }

    pub fn peek(&mut self) -> Option<u8> {
        if self.refill_buffer() {
            Some(self.buf[self.at])
        } else {
            None
        }
    }

    pub fn skip_whitespace(&mut self) {
        while let Some(b) = self.peek() {
            if !char::from(b).is_whitespace() {
                return;
            }
            self.get();
        }
    }

    pub fn next_token(&mut self) -> Option<Vec<u8>> {
        self.skip_whitespace();
        let mut res = Vec::new();
        while let Some(c) = self.get() {
            if char::from(c).is_whitespace() {
                break;
            }
            res.push(c);
        }
        if res.is_empty() {
            None
        } else {
            Some(res)
        }
    }

    //noinspection RsSelfConvention
    pub fn is_exhausted(&mut self) -> bool {
        self.peek().is_none()
    }

    pub fn read<T: Readable>(&mut self) -> T {
        T::read(self)
    }

    pub fn read_vec<T: Readable>(&mut self, size: usize) -> Vec<T> {
        let mut res = Vec::with_capacity(size);
        for _ in 0usize..size {
            res.push(self.read());
        }
        res
    }

    pub fn read_line(&mut self) -> String {
        let mut res = String::new();
        while let Some(c) = self.get() {
            if c == b'\n' {
                break;
            }
            if c == b'\r' {
                if self.peek() == Some(b'\n') {
                    self.get();
                }
                break;
            }
            res.push(c.into());
        }
        res
    }

    #[allow(clippy::should_implement_trait)]
    pub fn into_iter<T: Readable>(self) -> InputIterator<'s, T> {
        InputIterator {
            input: self,
            phantom: Default::default(),
        }
    }

    fn read_integer<T: FromStr>(&mut self) -> T
    where
        <T as FromStr>::Err: Debug,
    {
        let res = self.read_string();
        res.parse::<T>().unwrap()
    }

    fn read_string(&mut self) -> String {
        match self.next_token() {
            None => {
                panic!("Input exhausted");
            }
            Some(res) => unsafe { String::from_utf8_unchecked(res) },
        }
    }

    fn read_char(&mut self) -> char {
        self.skip_whitespace();
        self.get().unwrap().into()
    }

    fn read_float(&mut self) -> f64 {
        self.read_string().parse().unwrap()
    }

    fn refill_buffer(&mut self) -> bool {
        if self.at == self.buf_read {
            self.at = 0;
            self.buf_read = self.input.read(&mut self.buf).unwrap();
            self.buf_read != 0
        } else {
            true
        }
    }
}

pub trait Readable {
    fn read(input: &mut Input) -> Self;
}

impl Readable for String {
    fn read(input: &mut Input) -> Self {
        input.read_string()
    }
}

impl Readable for char {
    fn read(input: &mut Input) -> Self {
        input.read_char()
    }
}

impl Readable for f64 {
    fn read(input: &mut Input) -> Self {
        input.read_float()
    }
}

impl<T: Readable> Readable for Vec<T> {
    fn read(input: &mut Input) -> Self {
        let size = input.read();
        input.read_vec(size)
    }
}

pub struct InputIterator<'s, T: Readable> {
    input: Input<'s>,
    phantom: PhantomData<T>,
}

impl<'s, T: Readable> Iterator for InputIterator<'s, T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        self.input.skip_whitespace();
        self.input.peek().map(|_| self.input.read())
    }
}

macro_rules! read_integer {
    ($t:ident) => {
        impl Readable for $t {
            fn read(input: &mut Input) -> Self {
                input.read_integer()
            }
        }
    };
}

read_integer!(i8);
read_integer!(i16);
read_integer!(i32);
read_integer!(i64);
read_integer!(i128);
read_integer!(isize);
read_integer!(u8);
read_integer!(u16);
read_integer!(u32);
read_integer!(u64);
read_integer!(u128);
read_integer!(usize);

macro_rules! tuple_readable {
    ( $( $name:ident )+ ) => {
        impl<$($name: Readable), +> Readable for ($($name,)+) {
            fn read(input: &mut Input) -> Self {
                ($($name::read(input),)+)
            }
        }
    }
}

tuple_readable! {T}
tuple_readable! {T U}
tuple_readable! {T U V}
tuple_readable! {T U V X}
tuple_readable! {T U V X Y}
tuple_readable! {T U V X Y Z}
tuple_readable! {T U V X Y Z A}
tuple_readable! {T U V X Y Z A B}
tuple_readable! {T U V X Y Z A B C}
tuple_readable! {T U V X Y Z A B C D}
tuple_readable! {T U V X Y Z A B C D E}
tuple_readable! {T U V X Y Z A B C D E F}
}
pub mod output {
use std::io::Write;

pub struct Output {
    output: Box<dyn Write>,
    buf: Vec<u8>,
    at: usize,
    auto_flush: bool,
}

impl Output {
    const DEFAULT_BUF_SIZE: usize = 4096;

    pub fn new(output: Box<dyn Write>) -> Self {
        Self {
            output,
            buf: vec![0; Self::DEFAULT_BUF_SIZE],
            at: 0,
            auto_flush: false,
        }
    }

    pub fn new_with_auto_flush(output: Box<dyn Write>) -> Self {
        Self {
            output,
            buf: vec![0; Self::DEFAULT_BUF_SIZE],
            at: 0,
            auto_flush: true,
        }
    }

    pub fn flush(&mut self) {
        if self.at != 0 {
            self.output.write_all(&self.buf[..self.at]).unwrap();
            self.at = 0;
            self.output.flush().expect("Couldn't flush output");
        }
    }

    pub fn print<T: Writable>(&mut self, s: &T) {
        s.write(self);
    }

    pub fn put(&mut self, b: u8) {
        self.buf[self.at] = b;
        self.at += 1;
        if self.at == self.buf.len() {
            self.flush();
        }
    }

    pub fn maybe_flush(&mut self) {
        if self.auto_flush {
            self.flush();
        }
    }

    pub fn print_per_line<T: Writable>(&mut self, arg: &[T]) {
        for i in arg {
            i.write(self);
            self.put(b'\n');
        }
    }

    pub fn print_iter<T: Writable, I: Iterator<Item = T>>(&mut self, iter: I) {
        let mut first = true;
        for e in iter {
            if first {
                first = false;
            } else {
                self.put(b' ');
            }
            e.write(self);
        }
    }

    pub fn print_iter_ref<'a, T: 'a + Writable, I: Iterator<Item = &'a T>>(&mut self, iter: I) {
        let mut first = true;
        for e in iter {
            if first {
                first = false;
            } else {
                self.put(b' ');
            }
            e.write(self);
        }
    }
}

impl Write for Output {
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        let mut start = 0usize;
        let mut rem = buf.len();
        while rem > 0 {
            let len = (self.buf.len() - self.at).min(rem);
            self.buf[self.at..self.at + len].copy_from_slice(&buf[start..start + len]);
            self.at += len;
            if self.at == self.buf.len() {
                self.flush();
            }
            start += len;
            rem -= len;
        }
        if self.auto_flush {
            self.flush();
        }
        Ok(buf.len())
    }

    fn flush(&mut self) -> std::io::Result<()> {
        self.flush();
        Ok(())
    }
}

pub trait Writable {
    fn write(&self, output: &mut Output);
}

impl Writable for &str {
    fn write(&self, output: &mut Output) {
        output.write_all(self.as_bytes()).unwrap();
    }
}

impl Writable for String {
    fn write(&self, output: &mut Output) {
        output.write_all(self.as_bytes()).unwrap();
    }
}

impl Writable for char {
    fn write(&self, output: &mut Output) {
        output.put(*self as u8);
    }
}

impl<T: Writable> Writable for [T] {
    fn write(&self, output: &mut Output) {
        output.print_iter_ref(self.iter());
    }
}

impl<T: Writable> Writable for Vec<T> {
    fn write(&self, output: &mut Output) {
        self[..].write(output);
    }
}

macro_rules! write_to_string {
    ($t:ident) => {
        impl Writable for $t {
            fn write(&self, output: &mut Output) {
                self.to_string().write(output);
            }
        }
    };
}

write_to_string!(u8);
write_to_string!(u16);
write_to_string!(u32);
write_to_string!(u64);
write_to_string!(u128);
write_to_string!(usize);
write_to_string!(i8);
write_to_string!(i16);
write_to_string!(i32);
write_to_string!(i64);
write_to_string!(i128);
write_to_string!(isize);
write_to_string!(f32);
write_to_string!(f64);

impl<T: Writable, U: Writable> Writable for (T, U) {
    fn write(&self, output: &mut Output) {
        self.0.write(output);
        output.put(b' ');
        self.1.write(output);
    }
}

impl<T: Writable, U: Writable, V: Writable> Writable for (T, U, V) {
    fn write(&self, output: &mut Output) {
        self.0.write(output);
        output.put(b' ');
        self.1.write(output);
        output.put(b' ');
        self.2.write(output);
    }
}

pub static mut OUTPUT: Option<Output> = None;

pub fn output() -> &'static mut Output {
    unsafe {
        match &mut OUTPUT {
            None => {
                panic!("Panic");
            }
            Some(output) => output,
        }
    }
}

#[macro_export]
macro_rules! out {
    ($first: expr $(,$args:expr )*) => {
        output().print(&$first);
        $(output().put(b' ');
        output().print(&$args);
        )*
    }
}

#[macro_export]
macro_rules! out_line {
    ($first: expr $(, $args:expr )* ) => {
        out!($first $(,$args)*);
        output().put(b'\n');
    };
    () => {
        output().put(b'\n');
    };
}
}
}
fn main() {
    let mut sin = std::io::stdin();
    let input = crate::io::input::Input::new(&mut sin);
    unsafe {
        crate::io::output::OUTPUT = Some(crate::io::output::Output::new(Box::new(std::io::stdout())));
    }
    crate::solution::run(input);
}

use std::{
    fmt::Display,
    io::{self, prelude::*, BufWriter, Stdout, StdoutLock},
    ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Sub, SubAssign},
};

#[allow(unused_imports)]
use crate::{
    binary_search::*, ext::*, input::*, math::*, precompute::*, random::*, ranges::*,
    recursive_function::*,
};

#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ModPrime<const M: usize> {
    value: usize,
}
impl<const M: usize> ModPrime<M> {
    pub fn new(value: usize) -> Self {
        Self::from(value)
    }

    pub fn value(&self) -> usize {
        self.value
    }
}
impl<const M: usize> From<usize> for ModPrime<M> {
    fn from(value: usize) -> Self {
        Self { value: value % M }
    }
}
impl<const M: usize> Display for ModPrime<M> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.value.fmt(f)
    }
}
impl<const M: usize> AddAssign for ModPrime<M> {
    fn add_assign(&mut self, rhs: Self) {
        self.value = (self.value + rhs.value) % M;
    }
}
impl<const M: usize> SubAssign for ModPrime<M> {
    fn sub_assign(&mut self, rhs: Self) {
        self.value = (self.value + M - rhs.value) % M;
    }
}
impl<const M: usize> MulAssign for ModPrime<M> {
    fn mul_assign(&mut self, rhs: Self) {
        self.value = (self.value * rhs.value) % M;
    }
}
impl<const M: usize> DivAssign for ModPrime<M> {
    fn div_assign(&mut self, rhs: Self) {
        self.value = (self.value * pow_mod(rhs.value, M - 2, M)) % M;
    }
}
impl<const M: usize> RemAssign for ModPrime<M> {
    fn rem_assign(&mut self, rhs: Self) {
        self.value = self.value % rhs.value;
    }
}
impl<const M: usize> Add for ModPrime<M> {
    type Output = Self;
    fn add(mut self, rhs: Self) -> Self::Output {
        self += rhs;
        self
    }
}
impl<const M: usize> Sub for ModPrime<M> {
    type Output = Self;
    fn sub(mut self, rhs: Self) -> Self::Output {
        self -= rhs;
        self
    }
}
impl<const M: usize> Mul for ModPrime<M> {
    type Output = Self;
    fn mul(mut self, rhs: Self) -> Self::Output {
        self *= rhs;
        self
    }
}
impl<const M: usize> Div for ModPrime<M> {
    type Output = Self;
    fn div(mut self, rhs: Self) -> Self::Output {
        self /= rhs;
        self
    }
}
impl<const M: usize> Rem for ModPrime<M> {
    type Output = Self;
    fn rem(mut self, rhs: Self) -> Self::Output {
        self %= rhs;
        self
    }
}

#[derive(Debug, Clone)]
pub struct CombinatoricsModPrime<const M: usize> {
    inverses: Vec<ModPrime<M>>,
    factorials: Vec<ModPrime<M>>,
    factorial_inverses: Vec<ModPrime<M>>,
}
impl<const M: usize> CombinatoricsModPrime<M> {
    /// The caller is responsible of ensuring that M is a prime number
    pub fn precompute(max_value: usize) -> Self {
        let mut inverses = vec![1.into(); max_value + 1];
        let mut factorials = vec![1.into(); max_value + 1];
        let mut factorial_inverses = vec![1.into(); max_value + 1];
        for i in 2..=max_value {
            inverses[i] = ModPrime::new(M) - ModPrime::new(M / i) * inverses[M % i];
            factorials[i] = factorials[i - 1] * i.into();
            factorial_inverses[i] = factorial_inverses[i - 1] * inverses[i];
        }

        Self {
            inverses,
            factorials,
            factorial_inverses,
        }
    }

    pub fn inverse(&self, value: ModPrime<M>) -> ModPrime<M> {
        assert!(value.value != 0);
        self.inverses[value.value]
    }

    pub fn factorial(&self, value: ModPrime<M>) -> ModPrime<M> {
        self.factorials[value.value]
    }

    pub fn factorial_inverse(&self, value: ModPrime<M>) -> ModPrime<M> {
        self.factorial_inverses[value.value]
    }

    pub fn n_perm_k(&self, n: ModPrime<M>, k: ModPrime<M>) -> ModPrime<M> {
        if k.value == 0 {
            1.into()
        } else if n < k {
            0.into()
        } else {
            self.factorials[n.value] * self.factorial_inverses[(n - k).value]
        }
    }

    pub fn n_choose_k(&self, n: ModPrime<M>, k: ModPrime<M>) -> ModPrime<M> {
        if k.value == 0 || k == n {
            1.into()
        } else if n < k {
            0.into()
        } else {
            self.factorials[n.value]
                * self.factorial_inverses[k.value]
                * self.factorial_inverses[(n - k).value]
        }
    }

    pub fn inverse_usize(&self, value: usize) -> usize {
        self.inverse(value.into()).value
    }

    pub fn factorial_usize(&self, value: usize) -> usize {
        self.factorial(value.into()).value
    }

    pub fn factorial_inverse_usize(&self, value: usize) -> usize {
        self.factorial_inverse(value.into()).value
    }

    pub fn n_perm_k_usize(&self, n: usize, k: usize) -> usize {
        self.n_perm_k(n.into(), k.into()).value
    }

    pub fn n_choose_k_usize(&self, n: usize, k: usize) -> usize {
        self.n_choose_k(n.into(), k.into()).value
    }
}

const MOD: usize = 1e9 as usize + 7;

fn solve<R: BufRead>(read: &mut Scanner<R>) {
    let (n, k) = (read.u(), read.u());
    let comb = CombinatoricsModPrime::<MOD>::precompute(n);
    let mut total = ModPrime::new(0);
    for i in 0..=(k.min(n)) {
        total += comb.n_choose_k(n.into(), i.into());
    }
    outln!("{}", total);
}

fn main() {
    let stdin = io::stdin();
    let mut read = Scanner::new(stdin.lock());
    unsafe {
        OUTPUT.0 = Some(io::stdout());
        OUTPUT.1 = Some(BufWriter::new(OUTPUT.0.as_ref().unwrap_unchecked().lock()));
    }

    solve(&mut read);

    unsafe {
        OUTPUT.1.take();
    }
}

static mut OUTPUT: (Option<Stdout>, Option<BufWriter<StdoutLock<'static>>>) = (None, None);
#[macro_export]
macro_rules! out {
    ($($arg:tt)*) => {
        unsafe {
            write!(OUTPUT.1.as_mut().unwrap_unchecked(), $($arg)*).unwrap();
        }
    };
}
#[macro_export]
macro_rules! outln {
    ($($arg:tt)*) => {
        unsafe {
            writeln!(OUTPUT.1.as_mut().unwrap_unchecked(), $($arg)*).unwrap();
        }
    };
}
#[macro_export]
macro_rules! flush {
    () => {
        unsafe {
            OUTPUT.1.as_mut().unwrap_unchecked().flush().unwrap();
        }
    };
}

// Template -------------------------------------------------------------------
pub mod input {
    use std::{
        io::prelude::*,
        iter::{FromIterator, Peekable},
        mem,
        str::{self, FromStr, SplitWhitespace},
    };

    #[derive(Debug)]
    pub struct Scanner<R> {
        eof: bool,
        reader: R,
        buf_str: Vec<u8>,
        buf_iter: Peekable<SplitWhitespace<'static>>,
    }
    impl<R: BufRead> Scanner<R> {
        pub fn new(reader: R) -> Self {
            Self {
                eof: false,
                reader,
                buf_str: vec![],
                buf_iter: "".split_whitespace().peekable(),
            }
        }
        pub fn eof(&self) -> bool {
            self.eof
        }

        pub fn n<T: FromStr>(&mut self) -> T {
            self.read_until_next_token();
            self.buf_iter
                .next()
                .expect("No token")
                .parse()
                .ok()
                .expect("Failed parse")
        }
        pub fn u(&mut self) -> usize {
            self.n::<usize>()
        }
        pub fn i(&mut self) -> i64 {
            self.n::<i64>()
        }
        pub fn f(&mut self) -> f64 {
            self.n::<f64>()
        }
        pub fn s(&mut self) -> String {
            self.n::<String>()
        }
        #[allow(clippy::should_implement_trait)]
        pub fn next<T: FromStr>(&mut self) -> Option<T> {
            Some(self.buf_iter.next()?.parse().ok().expect("Failed parse"))
        }
        pub fn next_u(&mut self) -> Option<usize> {
            self.next::<usize>()
        }
        pub fn next_i(&mut self) -> Option<i64> {
            self.next::<i64>()
        }
        pub fn next_f(&mut self) -> Option<f64> {
            self.next::<f64>()
        }
        pub fn next_s(&mut self) -> Option<String> {
            self.next::<String>()
        }

        pub fn collection<C, T>(&mut self) -> C
        where
            C: FromIterator<T>,
            T: FromStr,
        {
            self.read_until_next_token();
            self.rest()
        }
        pub fn collection_n<C, T>(&mut self, n: usize) -> C
        where
            C: FromIterator<T>,
            T: FromStr,
        {
            (0..n).map(|_| self.n()).collect()
        }
        pub fn rest<C, T>(&mut self) -> C
        where
            C: FromIterator<T>,
            T: FromStr,
        {
            self.buf_iter
                .by_ref()
                .map(|v| v.parse().ok().expect("Failed parse"))
                .collect()
        }

        pub fn current_line(&self) -> &[u8] {
            &self.buf_str
        }
        pub fn read_line(&mut self) {
            assert!(!self.eof, "Tried to read after EOF");

            self.buf_str.clear();
            self.reader
                .read_until(b'\n', &mut self.buf_str)
                .expect("Failed read");

            if !self.buf_str.is_empty() && self.buf_str.last().unwrap() == &b'\n' {
                self.buf_str.pop();
            } else {
                self.eof = true;
            }

            self.buf_iter = unsafe {
                let slice = str::from_utf8_unchecked(&self.buf_str);
                mem::transmute(slice.split_whitespace().peekable())
            };
        }
        pub fn read_until_next_token(&mut self) {
            while !self.eof && self.buf_iter.peek().is_none() {
                self.read_line();
            }
        }
    }
}

pub mod num_traits {
    use std::ops::{
        Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div,
        DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub,
        SubAssign,
    };

    pub trait FromU8: Copy {
        fn from_u8(val: u8) -> Self;
    }
    macro_rules! from_u8_impl {
        ($($t: ident)+) => {$(
            impl FromU8 for $t {
                fn from_u8(val: u8) -> Self {
                    val as $t
                }
            }
        )+};
    }
    from_u8_impl!(i128 i64 i32 i16 i8 isize u128 u64 u32 u16 u8 usize f32 f64);

    pub trait ToF64: Copy {
        fn to_f64(self) -> f64;
    }
    macro_rules! to_f64_impl {
        ($($t: ident)+) => {$(
            impl ToF64 for $t {
                fn to_f64(self) -> f64 {
                    self as f64
                }
            }
        )+};
    }
    to_f64_impl!(i128 i64 i32 i16 i8 isize u128 u64 u32 u16 u8 usize f32 f64);

    pub trait Number:
        FromU8
        + ToF64
        + PartialOrd
        + Add<Output = Self>
        + Sub<Output = Self>
        + Mul<Output = Self>
        + Div<Output = Self>
        + Rem<Output = Self>
        + AddAssign
        + SubAssign
        + MulAssign
        + DivAssign
        + RemAssign
    {
    }
    macro_rules! number_impl {
        ($($t: ident)+) => {$(
            impl Number for $t {}
        )+};
    }
    number_impl!(i128 i64 i32 i16 i8 isize u128 u64 u32 u16 u8 usize f32 f64);

    pub trait Signed: Number + Neg<Output = Self> {}
    macro_rules! signed_impl {
        ($($t: ident)+) => {$(
            impl Signed for $t {}
        )+};
    }
    signed_impl!(i128 i64 i32 i16 i8 isize f32 f64);

    pub trait Unsigned: Number {}
    macro_rules! unsigned_impl {
        ($($t: ident)+) => {$(
            impl Unsigned for $t {}
        )+};
    }
    unsigned_impl!(u128 u64 u32 u16 u8 usize);

    pub trait Integer:
        Number
        + Ord
        + BitOr
        + BitAnd
        + BitXor
        + Shl
        + Shr
        + BitOrAssign
        + BitAndAssign
        + BitXorAssign
        + ShlAssign
        + ShrAssign
    {
    }
    macro_rules! integer_impl {
        ($($t: ident)+) => {$(
            impl Integer for $t {}
        )+};
    }
    integer_impl!(i128 i64 i32 i16 i8 isize u128 u64 u32 u16 u8 usize);

    pub trait Float: Number {}
    macro_rules! float_impl {
        ($($t: ident)+) => {$(
            impl Float for $t {}
        )+};
    }
    float_impl!(f32 f64);
}

pub mod ranges {
    use std::ops::{Range, RangeInclusive};

    use crate::{math, num_traits::Integer};

    #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
    pub struct DiscreteRange<T> {
        pub start: T,
        pub end: T,
    }
    impl<T: Integer> DiscreteRange<T> {
        pub fn is_empty(&self) -> bool {
            self.start >= self.end
        }

        pub fn len(&self) -> T {
            if self.is_empty() {
                T::from_u8(0)
            } else {
                self.end - self.start
            }
        }

        pub fn contains(&self, x: T) -> bool {
            self.start <= x && self.end > x
        }

        pub fn is_singleton(&self) -> bool {
            self.start + T::from_u8(1) == self.end
        }

        pub fn is_splittable(&self) -> bool {
            self.start + T::from_u8(1) < self.end
        }

        pub fn is_disjoint(&self, other: Self) -> bool {
            self.is_empty()
                || other.is_empty()
                || self.start >= other.end
                || self.end <= other.start
        }

        pub fn is_subset(&self, other: Self) -> bool {
            self.is_empty()
                || (!other.is_empty() && self.start >= other.start && self.end <= other.end)
        }

        pub fn is_superset(&self, other: Self) -> bool {
            other.is_subset(*self)
        }

        pub fn midpoint(&self) -> Option<T> {
            if self.is_empty() {
                None
            } else {
                Some(math::midpoint(self.start, self.end - T::from_u8(1)))
            }
        }

        pub fn split(&self) -> Option<(Self, Self)>
        where
            Self: Sized,
        {
            if self.is_splittable() {
                let mid_plus_one =
                    T::from_u8(1) + math::midpoint(self.start, self.end - T::from_u8(1));
                Some((
                    Self {
                        start: self.start,
                        end: mid_plus_one,
                    },
                    Self {
                        start: mid_plus_one,
                        end: self.end,
                    },
                ))
            } else {
                None
            }
        }

        pub fn iter(&self) -> Range<T> {
            self.start..self.end
        }
    }
    impl<T: Integer> From<Range<T>> for DiscreteRange<T> {
        fn from(range: Range<T>) -> Self {
            Self {
                start: range.start,
                end: range.end,
            }
        }
    }
    impl<T: Integer> From<RangeInclusive<T>> for DiscreteRange<T> {
        fn from(range: RangeInclusive<T>) -> Self {
            Self {
                start: *range.start(),
                end: *range.end() + T::from_u8(1),
            }
        }
    }
}

pub mod ext {
    use crate::num_traits::Float;

    #[allow(clippy::derive_partial_eq_without_eq)]
    #[derive(Debug, Clone, Copy, Default, PartialEq, PartialOrd, Hash)]
    pub struct OrdFloat<T>(pub T);
    impl<T: Float> Eq for OrdFloat<T> {}
    #[allow(clippy::derive_ord_xor_partial_ord)]
    impl<T: Float> Ord for OrdFloat<T> {
        fn cmp(&self, other: &Self) -> std::cmp::Ordering {
            self.0.partial_cmp(&other.0).unwrap()
        }
    }
}

pub mod math {
    use std::{mem, ops::RangeFrom};

    use crate::num_traits::{Integer, Number, Unsigned};

    /// Rounds towards a if the type is an integer
    /// Risks overflowing if a and b have different signs
    pub fn midpoint<T>(a: T, b: T) -> T
    where
        T: Number,
    {
        a + (b - a) / T::from_u8(2)
    }

    pub fn gcd<T>(mut a: T, mut b: T) -> T
    where
        T: Integer + Unsigned,
    {
        while b != T::from_u8(0) {
            a %= b;
            mem::swap(&mut a, &mut b);
        }
        a
    }

    pub fn lcm<T>(a: T, b: T) -> T
    where
        T: Integer + Unsigned,
    {
        (a / gcd(a, b)) * b
    }

    pub fn pow_mod<T>(b: T, e: T, modulo: T) -> T
    where
        T: Integer + Unsigned,
    {
        if e == T::from_u8(0) {
            T::from_u8(1) % modulo
        } else {
            let half = pow_mod(b, e / T::from_u8(2), modulo);
            let combined = (half * half) % modulo;
            if e % T::from_u8(2) == T::from_u8(1) {
                (combined * b) % modulo
            } else {
                combined
            }
        }
    }

    pub fn is_prime<T>(n: T) -> bool
    where
        T: Integer + Unsigned,
        RangeFrom<T>: Iterator<Item = T>,
    {
        if n < T::from_u8(2) {
            false
        } else {
            for x in (T::from_u8(2)..).take_while(|&x| x * x <= n) {
                if n % x == T::from_u8(0) {
                    return false;
                }
            }
            true
        }
    }
}

pub mod precompute {
    #[derive(Debug, Clone)]
    pub struct Logarithms {
        /// index.log2() rounded down
        log2: Vec<usize>,
        /// greatest power of 2 <= index
        previous_power_of_two: Vec<usize>,
    }
    impl Logarithms {
        pub fn precompute(max_value: usize) -> Self {
            let mut log2 = vec![0; max_value + 1];
            let mut previous_power_of_two = vec![1; max_value + 1];
            for i in 2..=max_value {
                log2[i] = log2[i / 2] + 1;
                previous_power_of_two[i] = 1 << log2[i];
            }
            Self {
                log2,
                previous_power_of_two,
            }
        }

        pub fn log2(&self, value: usize) -> usize {
            assert!(value != 0);
            self.log2[value]
        }

        pub fn previous_power_of_two(&self, value: usize) -> usize {
            assert!(value != 0);
            self.previous_power_of_two[value]
        }
    }
}

pub mod binary_search {
    use crate::{math, num_traits::Integer, ranges::DiscreteRange};

    pub fn binary_search_first_true<T>(range: DiscreteRange<T>, mut p: impl FnMut(T) -> bool) -> T
    where
        T: Integer,
    {
        let mut low = range.start;
        let mut high = range.end;
        while low < high {
            let mid = math::midpoint(low, high);
            if p(mid) {
                high = mid;
            } else {
                low = mid + T::from_u8(1);
            }
        }
        high
    }

    pub fn partition_point<T>(range: DiscreteRange<T>, mut p: impl FnMut(T) -> bool) -> T
    where
        T: Integer,
    {
        binary_search_first_true(range, |i| !p(i))
    }
}

pub mod random {
    use std::{num::Wrapping, time::SystemTime};

    /// Pcg32 from https://docs.rs/pcg_rand/0.13.0/src/pcg_rand/lib.rs.html#406
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
    pub struct Random {
        state: u64,
        inc: u64,
    }
    impl Random {
        pub fn random_seed() -> Self {
            let time = SystemTime::now()
                .duration_since(std::time::UNIX_EPOCH)
                .expect("Duration since epoch failed");
            Self {
                state: (time.as_nanos() as u32) as u64,
                inc: time.subsec_nanos() as u64,
            }
        }

        pub fn from_seed(seed: [u64; 2]) -> Self {
            Self {
                state: seed[0],
                inc: seed[1],
            }
        }

        pub fn next_u32(&mut self) -> u32 {
            let oldstate = Wrapping(self.state);
            self.state =
                (oldstate * Wrapping(6_364_136_223_846_793_005u64) + Wrapping(self.inc | 1)).0;
            let xorshifted: u32 = (((oldstate >> 18usize) ^ oldstate) >> 27usize).0 as u32;
            let rot: u32 = (oldstate >> 59usize).0 as u32;
            (xorshifted >> rot) | (xorshifted << ((-(rot as i32)) & 31))
        }
    }
}

#[allow(clippy::too_many_arguments)]
pub mod recursive_function {
    use std::marker::PhantomData;

    macro_rules! recursive_function {
        ($name: ident, $trait: ident, ($($type: ident $arg: ident,)*)) => {
            pub trait $trait<$($type, )*Output> {
                fn call(&mut self, $($arg: $type,)*) -> Output;
            }

            pub struct $name<F, $($type, )*Output>
            where
                F: FnMut(&mut dyn $trait<$($type, )*Output>, $($type, )*) -> Output,
            {
                f: std::cell::UnsafeCell<F>,
                $($arg: PhantomData<$type>,
                )*
                phantom_output: PhantomData<Output>,
            }

            impl<F, $($type, )*Output> $name<F, $($type, )*Output>
            where
                F: FnMut(&mut dyn $trait<$($type, )*Output>, $($type, )*) -> Output,
            {
                pub fn new(f: F) -> Self {
                    Self {
                        f: std::cell::UnsafeCell::new(f),
                        $($arg: Default::default(),
                        )*
                        phantom_output: Default::default(),
                    }
                }
            }

            impl<F, $($type, )*Output> $trait<$($type, )*Output> for $name<F, $($type, )*Output>
            where
                F: FnMut(&mut dyn $trait<$($type, )*Output>, $($type, )*) -> Output,
            {
                fn call(&mut self, $($arg: $type,)*) -> Output {
                    unsafe { (&mut *self.f.get())(self, $($arg, )*) }
                }
            }
        }
    }

    recursive_function!(RecursiveFunction0, Callable0, ());
    recursive_function!(RecursiveFunction, Callable, (Arg arg,));
    recursive_function!(RecursiveFunction2, Callable2, (Arg1 arg1, Arg2 arg2,));
    recursive_function!(RecursiveFunction3, Callable3, (Arg1 arg1, Arg2 arg2, Arg3 arg3,));
    recursive_function!(RecursiveFunction4, Callable4, (Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4,));
    recursive_function!(RecursiveFunction5, Callable5, (Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5,));
    recursive_function!(RecursiveFunction6, Callable6, (Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6,));
    recursive_function!(RecursiveFunction7, Callable7, (Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6, Arg7 arg7,));
    recursive_function!(RecursiveFunction8, Callable8, (Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6, Arg7 arg7, Arg8 arg8,));
    recursive_function!(RecursiveFunction9, Callable9, (Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6, Arg7 arg7, Arg8 arg8, Arg9 arg9,));
}

use std::{
    io::{prelude::*, stdin, stdout, BufWriter},
    iter::once,
};

const MOD: i64 = 1000000007;

fn main() {
    let std_in = stdin();
    let mut input = Scanner::new(std_in.lock());

    let std_out = stdout();
    let mut output = BufWriter::new(std_out.lock());

    let (n, k): (i64, i64) = (input.token(), input.token());
    if k >= n {
        writeln!(output, "{}", bin_pow_m(2, n)).unwrap();
    } else {
        let fact: Vec<i64> = once(1)
            .chain((1..=n).scan(1i64, |state, x| {
                *state = mul_m(*state, x);
                Some(*state)
            }))
            .collect();
        let inv_fact: Vec<i64> = fact.iter().map(|&x| bin_pow_m(x, MOD - 2)).collect();

        let mut result = 0;
        for i in 0..=(k as usize) {
            result = add_m(result, mul_m(inv_fact[i], inv_fact[n as usize - i]));
        }
        result = mul_m(result, fact[n as usize]);
        writeln!(output, "{}", result).unwrap();
    }
}

fn add_m(x: i64, y: i64) -> i64 {
    let mut tmp = x + y;
    if tmp < 0 {
        tmp += MOD;
    }
    if tmp >= MOD {
        tmp -= MOD;
    }
    tmp
}

fn mul_m(x: i64, y: i64) -> i64 {
    (x * y) % MOD
}

fn bin_pow_m(mut a: i64, mut n: i64) -> i64 {
    let mut res = 1;
    while n != 0 {
        if (n & 1) != 0 {
            res = mul_m(res, a);
        }
        a = mul_m(a, a);
        n >>= 1;
    }
    res
}

pub struct Scanner<B> {
    reader: B,
    buf_str: Vec<u8>,
    buf_iter: std::str::SplitWhitespace<'static>,
}
impl<B: BufRead> Scanner<B> {
    pub fn new(reader: B) -> Self {
        Self {
            reader,
            buf_str: Vec::new(),
            buf_iter: "".split_whitespace(),
        }
    }
    pub fn token<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buf_iter.next() {
                return token.parse().ok().expect("Failed parse");
            }
            self.buf_str.clear();
            self.reader
                .read_until(b'\n', &mut self.buf_str)
                .expect("Failed read");
            self.buf_iter = unsafe {
                let slice = std::str::from_utf8_unchecked(&self.buf_str);
                std::mem::transmute(slice.split_whitespace())
            }
        }
    }
}

#![allow(unused_imports)]
#![allow(unused_must_use)]
#![allow(unused_macros)]
#![allow(non_snake_case)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::many_single_char_names)]
#![allow(clippy::needless_range_loop)]
#![allow(clippy::comparison_chain)]

use std::cmp::{max, min, Reverse};
use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque};
use std::io::{self, prelude::*};
use std::str;

fn solve<R: BufRead, W: Write>(sc: &mut Scanner<R>, wr: &mut W) {
    const MOD: i64 = 1_000_000_007;
    let n: i64 = sc.tok();
    let k: i64 = sc.tok();
    let mut cur = 1;
    let mut res = 1;
    for a in 1..=min(n, k) {
        cur = (cur * mod_inv(a, MOD)) % MOD;
        cur = (cur * (n - a + 1)) % MOD;
        res += cur;
        if res >= MOD {
            res -= MOD;
        }
    }
    writeln!(wr, "{}", res);
}

/// Returns x, y such that ax + by = gcd(a, b);
/// Assumes a, b are >= 0
pub fn extended_euclid(a: i64, b: i64) -> (i64, i64, i64) {
    let (mut x1, mut y1, mut z1) = (1i64, 0i64, a);
    let (mut x2, mut y2, mut z2) = (0i64, 1i64, b);
    while z2 > 0 {
        let k = z1 / z2;
        let (x3, y3, z3) = (x1 - k * x2, y1 - k * y2, z1 - k * z2);
        (x1, y1, z1) = (x2, y2, z2);
        (x2, y2, z2) = (x3, y3, z3);
    }
    (x1, y1, z1)
}

/// Finds the inverse of a mod m.
/// Assumes they are relatively prime and m > 0
pub fn mod_inv(mut a: i64, m: i64) -> i64 {
    a %= m;
    if a < 0 {
        a += m;
    }
    let res = extended_euclid(a, m).0 % m;
    if res < 0 {
        res + m
    } else {
        res
    }
}

use std::marker::PhantomData;
macro_rules! recursive_function {
    ($name: ident, $trait: ident, ($($type: ident $arg: ident,)*)) => {
        pub trait $trait<$($type, )*Output> {
            fn call(&mut self, $($arg: $type,)*) -> Output;
        }

        pub struct $name<F, $($type, )*Output>
        where
            F: FnMut(&mut dyn $trait<$($type, )*Output>, $($type, )*) -> Output,
        {
            f: F,
            $($arg: PhantomData<$type>,
            )*
            phantom_output: PhantomData<Output>,
        }

        impl<F, $($type, )*Output> $name<F, $($type, )*Output>
        where
            F: FnMut(&mut dyn $trait<$($type, )*Output>, $($type, )*) -> Output,
        {
            pub fn new(f: F) -> Self {
                Self {
                    f,
                    $($arg: Default::default(),
                    )*
                    phantom_output: Default::default(),
                }
            }
        }

        impl<F, $($type, )*Output> $trait<$($type, )*Output> for $name<F, $($type, )*Output>
        where
            F: FnMut(&mut dyn $trait<$($type, )*Output>, $($type, )*) -> Output,
        {
            fn call(&mut self, $($arg: $type,)*) -> Output {
                let const_ptr = &self.f as *const F;
                let mut_ptr = const_ptr as *mut F;
                unsafe { (&mut *mut_ptr)(self, $($arg, )*) }
            }
        }
    }
}

recursive_function!(RecursiveFunction0, Callable0, ());
recursive_function!(RecursiveFunction, Callable, (Arg arg,));
recursive_function!(RecursiveFunction2, Callable2, (Arg1 arg1, Arg2 arg2,));
recursive_function!(RecursiveFunction3, Callable3, (Arg1 arg1, Arg2 arg2, Arg3 arg3,));
recursive_function!(RecursiveFunction4, Callable4, (Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4,));
recursive_function!(RecursiveFunction5, Callable5, (Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5,));
recursive_function!(RecursiveFunction6, Callable6, (Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6,));
recursive_function!(RecursiveFunction7, Callable7, (Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6, Arg7 arg7,));
recursive_function!(RecursiveFunction8, Callable8, (Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6, Arg7 arg7, Arg8 arg8,));
recursive_function!(RecursiveFunction9, Callable9, (Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6, Arg7 arg7, Arg8 arg8, Arg9 arg9,));

#[macro_export]
macro_rules! dbg{
    ($($a:expr),*) => {
        #[cfg(debug_assertions)]
        eprintln!(
            concat!("{}:{}:{}: ",$(stringify!($a), " = {:?}, "),*),
            file!(), line!(), column!(), $($a),*
        );
        #[cfg(not(debug_assertions))]
        {};
    }
}
struct Scanner<R> {
    reader: R,
    buf_str: Vec<u8>,
    buf_iter: str::SplitWhitespace<'static>,
}
impl<R: BufRead> Scanner<R> {
    fn new(reader: R) -> Self {
        Self {
            reader,
            buf_str: vec![],
            buf_iter: "".split_whitespace(),
        }
    }
    fn tok<T: str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buf_iter.next() {
                return token.parse().ok().expect("Failed parse");
            }
            self.buf_str.clear();
            self.reader
                .read_until(b'\n', &mut self.buf_str)
                .expect("Failed read");
            self.buf_iter = unsafe {
                let slice = str::from_utf8_unchecked(&self.buf_str);
                std::mem::transmute(slice.split_whitespace())
            }
        }
    }
}

fn main() {
    let (stdin, stdout) = (io::stdin(), io::stdout());
    let mut scan = Scanner::new(stdin.lock());
    let mut out = io::BufWriter::new(stdout.lock());
    solve(&mut scan, &mut out);
}

#![allow(dead_code, unused_macros, unused_imports)]
use std::{cell::{Cell, RefCell, UnsafeCell}, cmp::{Ordering, Reverse, max, min}, collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque, hash_map::{DefaultHasher, RandomState}}, error::Error, fmt::{Display, Write as FmtWrite}, hash::{BuildHasher, Hash, Hasher}, io::{BufWriter, Read, Stdin, Stdout, Write}, iter::{FromIterator, Peekable}, mem::swap, ops::*, process::exit, rc::Rc, str::{FromStr, from_utf8_unchecked}, time::{Duration, Instant}, convert::{TryInto, TryFrom}, marker::PhantomData};

const IO_BUF_SIZE: usize = 1 << 16;
type Input = Scanner<Stdin>;
type Output = BufWriter<Stdout>;
fn _init_input() -> Input { Scanner::new(std::io::stdin()) }
fn _init_output() -> Output { BufWriter::with_capacity(IO_BUF_SIZE, std::io::stdout()) }

#[repr(transparent)] struct Unsync<T>(T);
unsafe impl<T> Sync for Unsync<T> {}

type BadLazy<T> = Unsync<UnsafeCell<Option<T>>>;
impl<T> BadLazy<T> {
    const fn new() -> Self { Self(UnsafeCell::new(None)) }
}

static INPUT: BadLazy<Input> = BadLazy::new();
static OUTPUT: BadLazy<Output> = BadLazy::new();

fn inp<F: FnOnce(&mut Input) -> R, R>(f: F) -> R {
    unsafe { f((&mut *INPUT.0.get()).get_or_insert_with(_init_input)) }
}
fn out<F: FnOnce(&mut Output) -> R, R>(f: F) -> R {
    unsafe { f((&mut *OUTPUT.0.get()).get_or_insert_with(_init_output)) }
}

macro_rules! read {
    () => { read() };
    ($t: ty) => { read::<$t>() };
    ($t: ty, $($tt: ty),*) => { (read::<$t>(), $(read::<$tt>(),)*) };
    [$t: ty; $n: expr] => { read_vec::<$t>($n) };
}
macro_rules! println {
    () => { out(|x| { let _ = writeln!(x); }) };
    ($exp: expr) => { out(|x| { let _ = writeln!(x, "{}", $exp); }) };
    ($fmt: expr, $($arg : tt )*) => { out(|x| { let _ = writeln!(x, $fmt, $($arg)*); }) }
}
macro_rules! print {
    ($exp: expr) => { out(|x| { let _ = write!(x, "{}", $exp); }) };
    ($fmt: expr, $($arg : tt )*) => { out(|x| { let _ = write!(x, $fmt, $($arg)*); }) }
}

fn out_flush() { out(|x| { let _ = x.flush(); }); }

fn input_is_eof() -> bool { inp(|x| x.eof()) }
fn read_byte() -> u8 { inp(|x| x.byte()) }
fn read_bytes_no_skip(n: usize) -> Vec<u8> { inp(|x| x.bytes_no_skip(n)) }
fn read_bytes(n: usize) -> Vec<u8> { inp(|x| x.bytes(n)) }
fn read_bytes2(n: usize, m: usize) -> Vec<Vec<u8>> { inp(|x| x.bytes2(n, m)) }
fn read_token() -> Vec<u8> { inp(|x| x.token_bytes()) }
fn read_token_str() -> String { unsafe { String::from_utf8_unchecked(read_token()) } }
fn read_line() -> Vec<u8> { inp(|x| x.line_bytes()) }
fn read_line_str() -> String { unsafe { String::from_utf8_unchecked(read_line()) } }
fn read<T: FromStr>() -> T { read_token_str().parse::<T>().ok().expect("failed parse") }
fn read_vec<T: FromStr>(n: usize) -> Vec<T> { (0..n).map(|_| read()).collect() }
fn read_vec2<T: FromStr>(n: usize, m: usize) -> Vec<Vec<T>> { (0..n).map(|_| read_vec(m)).collect() }

struct Scanner<R: Read> {
    src: R,
    _buf: Vec<u8>,
    _pt: usize, // pointer
    _rd: usize, // bytes read
}

#[allow(dead_code)]
impl<R: Read> Scanner<R> {
    fn new(src: R) -> Scanner<R> {
        Scanner { src, _buf: vec![0; IO_BUF_SIZE], _pt: 1, _rd: 1 }
    }

    fn _check_buf(&mut self) {
        if self._pt == self._rd {
            self._rd = self.src.read(&mut self._buf).unwrap_or(0);
            self._pt = (self._rd == 0) as usize;
        }
    }

    // returns true if end of file
    fn eof(&mut self) -> bool {
        self._check_buf();
        self._rd == 0
    }

    // filters \r, returns \0 if eof
    fn byte(&mut self) -> u8 {
        loop {
            self._check_buf();
            if self._rd == 0 { return 0; }
            let res = self._buf[self._pt];
            self._pt += 1;
            if res != b'\r' { return res; }
        }
    }

    fn bytes_no_skip(&mut self, n: usize) -> Vec<u8> { (0..n).map(|_| self.byte()).collect() }
    fn bytes(&mut self, n: usize) -> Vec<u8> {
        let res = self.bytes_no_skip(n);
        self.byte();
        res
    }
    fn bytes2(&mut self, n: usize, m: usize) -> Vec<Vec<u8>> { (0..n).map(|_| self.bytes(m)).collect() }

    fn token_bytes(&mut self) -> Vec<u8> {
        let mut res = Vec::new();
        let mut c = self.byte();
        while c <= b' ' {
            if c == b'\0' { return res; }
            c = self.byte();
        }
        loop {
            res.push(c);
            c = self.byte();
            if c <= b' ' { return res; }
        }
    }

    fn line_bytes(&mut self) -> Vec<u8> {
        let mut res = Vec::new();
        let mut c = self.byte();
        while c != b'\n' && c != b'\0' {
            res.push(c);
            c = self.byte();
        }
        res
    }
}

trait JoinToStr {
    fn join_to_str(self, sep: &str) -> String;
    fn concat_to_str(self) -> String;
}
impl<T: Display, I: Iterator<Item = T>> JoinToStr for I {
    fn join_to_str(mut self, sep: &str) -> String {
        match self.next() {
            Some(first) => {
                let mut res = first.to_string();
                while let Some(item) = self.next() {
                    res.push_str(sep);
                    res.push_str(&item.to_string());
                }
                res
            }
            None => { String::new() }
        }
    }

    fn concat_to_str(self) -> String {
        let mut res = String::new();
        for item in self { res.push_str(&item.to_string()); }
        res
    }
}
trait AsStr { fn as_str(&self) -> &str; }
impl AsStr for [u8] { fn as_str(&self) -> &str {std::str::from_utf8(self).expect("attempt to convert non-UTF8 byte string.")} }

macro_rules! veci {
    ($n:expr , $i:ident : $gen:expr) => {{
        let _veci_n = $n;
        let mut _veci_list = Vec::with_capacity(_veci_n);
        for $i in 0.._veci_n {
            _veci_list.push($gen);
        }
        _veci_list
    }};
    ($n:expr , $gen:expr) => { veci!($n, _veci_: $gen) }
}

fn abs_diff<T: Sub<Output = T> + PartialOrd>(x: T, y: T) -> T {
    if x < y { y - x } else { x - y }
}

trait CommonNumExt {
    fn div_ceil(self, b: Self) -> Self;
    fn div_floor(self, b: Self) -> Self;
    fn gcd(self, b: Self) -> Self;
    fn highest_one(self) -> Self;
    fn lowest_one(self) -> Self;
    fn sig_bits(self) -> u32;
}

macro_rules! impl_common_num_ext {
    ($($ix:tt = $ux:tt),*) => {
        $(
            impl CommonNumExt for $ux {
                fn div_ceil(self, b: Self) -> Self {
                    let q = self / b; let r = self % b;
                    if r != 0 { q + 1 } else { q }
                }
                fn div_floor(self, b: Self) -> Self { self / b }
                fn gcd(self, mut b: Self) -> Self {
                    let mut a = self;
                    if a == 0 || b == 0 { return a | b; }
                    let shift = (a | b).trailing_zeros();
                    a >>= a.trailing_zeros();
                    b >>= b.trailing_zeros();
                    while a != b {
                        if a > b { a -= b; a >>= a.trailing_zeros(); }
                        else { b -= a; b >>= b.trailing_zeros(); }
                    }
                    a << shift
                }
                #[inline] fn highest_one(self) -> Self {
                    if self == 0 { 0 } else { const ONE: $ux = 1; ONE << self.sig_bits() - 1 }
                }
                #[inline] fn lowest_one(self) -> Self { self & self.wrapping_neg() }
                #[inline] fn sig_bits(self) -> u32 { std::mem::size_of::<$ux>() as u32 * 8 - self.leading_zeros() }
            }

            impl CommonNumExt for $ix {
                fn div_ceil(self, b: Self) -> Self {
                    let q = self / b; let r = self % b;
                    if self ^ b >= 0 && r != 0 { q + 1 } else { q }
                }
                fn div_floor(self, b: Self) -> Self {
                    let q = self / b; let r = self % b;
                    if self ^ b < 0 && r != 0 { q - 1 } else { q }
                }
                fn gcd(self, b: Self) -> Self {
                    fn w_abs(x: $ix) -> $ux { (if x.is_negative() { x.wrapping_neg() } else { x }) as _ }
                    w_abs(self).gcd(w_abs(b)) as _
                }
                #[inline] fn highest_one(self) -> Self { (self as $ux).highest_one() as _ }
                #[inline] fn lowest_one(self) -> Self { self & self.wrapping_neg() }
                #[inline] fn sig_bits(self) -> u32 { std::mem::size_of::<$ix>() as u32 * 8 - self.leading_zeros() }
            }
        )*
    }
}
impl_common_num_ext!(i8 = u8, i16 = u16, i32 = u32, i64 = u64, i128 = u128, isize = usize);

trait ChMaxMin<T> {
    fn chmax(&mut self, v: T) -> bool;
    fn chmin(&mut self, v: T) -> bool;
}
impl<T: PartialOrd> ChMaxMin<T> for Option<T> {
    fn chmax(&mut self, v: T) -> bool { if self.is_none() || v > *self.as_ref().unwrap() { *self = Some(v); true } else { false } }
    fn chmin(&mut self, v: T) -> bool { if self.is_none() || v < *self.as_ref().unwrap() { *self = Some(v); true } else { false } }
}
impl<T: PartialOrd> ChMaxMin<T> for T {
    fn chmax(&mut self, v: T) -> bool { if v > *self { *self = v; true } else { false } }
    fn chmin(&mut self, v: T) -> bool { if v < *self { *self = v; true } else { false } }
}

// * end commons * //

#[macro_use]
#[allow(dead_code)]
mod modint {
    use std::{fmt::{Display, Formatter}, marker::PhantomData, mem::swap, ops::*, str::FromStr, cell::Cell};
    use crate::ModInt;

    pub trait RemEuclidU32: Copy {
        /// Calculates `self` _mod_ `modulus` losslessly.
        fn rem_euclid_u32(self, modulus: u32) -> u32;
    }

    macro_rules! impl_rem_euclid_u32_for_small_signed {
        ($($ty:tt),*) => {
            $(
                impl RemEuclidU32 for $ty {
                    #[inline]
                    fn rem_euclid_u32(self, modulus: u32) -> u32 {
                        (self as i64).rem_euclid(i64::from(modulus)) as _
                    }
                }
            )*
        }
    }

    impl_rem_euclid_u32_for_small_signed!(i8, i16, i32, i64, isize);

    impl RemEuclidU32 for i128 {
        #[inline]
        fn rem_euclid_u32(self, modulus: u32) -> u32 {
            self.rem_euclid(i128::from(modulus)) as _
        }
    }

    macro_rules! impl_rem_euclid_u32_for_small_unsigned {
        ($($ty:tt),*) => {
            $(
                impl RemEuclidU32 for $ty {
                    #[inline]
                    fn rem_euclid_u32(self, modulus: u32) -> u32 {
                        self as u32 % modulus
                    }
                }
            )*
        }
    }

    macro_rules! impl_rem_euclid_u32_for_large_unsigned {
        ($($ty:tt),*) => {
            $(
                impl RemEuclidU32 for $ty {
                    #[inline]
                    fn rem_euclid_u32(self, modulus: u32) -> u32 {
                        (self % (modulus as $ty)) as _
                    }
                }
            )*
        }
    }

    impl_rem_euclid_u32_for_small_unsigned!(u8, u16, u32);
    impl_rem_euclid_u32_for_large_unsigned!(u64, u128);

    #[cfg(target_pointer_width = "32")]
    impl_rem_euclid_u32_for_small_unsigned!(usize);

    #[cfg(target_pointer_width = "64")]
    impl_rem_euclid_u32_for_large_unsigned!(usize);
    #[inline]
    pub fn mul_mod_u32(a: u32, b: u32, m: u32) -> u32 {
        (a as u64 * b as u64 % m as u64) as u32
    }

    // for a, b < m, unspecified otherwise
    #[inline]
    fn add_mod_raw(a: u32, b: u32, m: u32) -> u32 {
        let (r, c) = a.wrapping_sub(m).overflowing_add(b);
        if c { r } else { a + b }
    }
    #[inline]
    fn sub_mod_raw(a: u32, b: u32, m: u32) -> u32 {
        let (r, c) = a.overflowing_sub(b);
        if c { r.wrapping_add(m) } else { r }
    }
    fn pow_mod_raw(a: u32, mut k: u64, m: u32) -> u32 {
        if m == 1 { return 0; }
        let mut a = a as u64;
        let m = m as u64;
        let mut r: u64 = 1;
        while k > 0 {
            if k & 1 == 1 {
                r = r * a % m;
            }
            k >>= 1;
            a = a * a % m;
        }
        r as u32
    }

    /// # Parameters
    /// * `b` `1 <= b`
    /// # Returns
    /// (x, g) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
    fn inv_gcd(a: i64, b: i64) -> (i64, i64) {
        let a = a.rem_euclid(b);
        if a == 0 { return (0, b); }
        let mut s = b;
        let mut t = a;
        let mut m0 = 0;
        let mut m1 = 1;

        while t != 0 {
            let u = s / t;
            s -= t * u;
            m0 -= m1 * u;
            swap(&mut s, &mut t);
            swap(&mut m0, &mut m1);
        }

        if m0 < 0 { m0 += b / s; }
        (m0, s)
    }

    pub trait Modulus: Copy + Eq {
        fn get_modulus() -> u32;
        fn mul(a: u32, b: u32) -> u32;
    }

    #[derive(Clone, Copy, PartialEq, Eq, Hash)]
    #[repr(transparent)]
    pub struct ModIntBase<M: Modulus> {
        val: u32,
        _phantom: PhantomData<M>
    }

    impl <M: Modulus> ModIntBase<M> {
        #[inline(always)]
        pub fn modulus() -> u32 { M::get_modulus() }
        #[inline] pub fn new<I: RemEuclidU32>(val: I) -> Self { Self::raw(val.rem_euclid_u32(Self::modulus())) }
        #[inline] pub fn raw(val: u32) -> Self { Self { val, _phantom: PhantomData } }
        pub fn inv(self) -> Self {
            let (x, gcd) = inv_gcd(self.val.into(), Self::modulus().into());
            debug_assert!(gcd == 1, "the multiplicative inverse {}^-1 mod {} does not exist", self.val, Self::modulus());
            Self::raw(x as u32)
        }
        #[inline] pub fn val(self) -> u32 { self.val }
        #[inline] pub fn pow(self, k: u64) -> Self {
            Self::raw(pow_mod_raw(self.val, k, Self::modulus()))
        }
        pub fn powi(self, k: i64) -> Self { if k < 0 { self.inv().pow(-k as _) } else { self.pow(k as _) } }
        pub fn pow_vec(self, n: usize) -> Vec<Self> {
            let mut res = vec![Self::raw(0); n+1];
            res[0] += 1;
            for i in 1..=n {
                res[i] = res[i-1] * self;
            }
            res
        }

        pub fn invs(a: &[Self]) -> Vec<Self> {
            let n = a.len();
            if n == 0 { return vec![]; }
            let mut acc = Self::new(1);
            let mut res = Vec::with_capacity(n);
            for i in 0..n {
                if a[i].val() != 0 { acc *= a[i]; }
                res.push(acc);
            }
            acc = acc.inv();
            for i in (1..n).rev() {
                res[i] = acc * res[i-1];
                if a[i].val() != 0 { acc *= a[i]; }
            }
            res[0] = acc;
            res
        }
    }

    #[inline]
    pub fn mi<I: RemEuclidU32>(val: I) -> ModInt { ModIntBase::new(val) }
    #[inline] pub fn mir(v: u32) -> ModInt { ModIntBase::raw(v) }

    impl<V: RemEuclidU32, M: Modulus> From<V> for ModIntBase<M> {
        #[inline]
        fn from(from: V) -> Self { Self::new(from) }
    }
    impl<M: Modulus> Default for ModIntBase<M> {
        fn default() -> Self { Self::raw(0) }
    }
    impl<M: Modulus> FromStr for ModIntBase<M> {
        type Err = std::convert::Infallible;
        #[inline]
        fn from_str(s: &str) -> Result<Self, Self::Err> {
            Ok(s.parse::<i64>()
            .map(Self::new)
            .unwrap_or_else(|_| todo!("parsing as an arbitrary precision integer?")))
        }
    }
    impl<M: Modulus> Display for ModIntBase<M> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
            self.val.fmt(f)
        }
    }
    impl<M: Modulus> std::fmt::Debug for ModIntBase<M> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
            std::fmt::Debug::fmt(&self.val, f)
        }
    }
    impl<M: Modulus> Neg for ModIntBase<M> {
        type Output = Self;

        #[inline]
        fn neg(self) -> Self::Output {
            Self::raw(0) - self
        }
    }

    impl<V: Into<ModIntBase<M>>, M: Modulus> Add<V> for ModIntBase<M> {
        type Output = Self;
        #[inline]
        fn add(self, rhs: V) -> Self::Output {
            Self::raw(add_mod_raw(self.val, rhs.into().val, Self::modulus()))
        }
    }
    impl<V: Into<ModIntBase<M>>, M: Modulus> Sub<V> for ModIntBase<M> {
        type Output = Self;
        #[inline]
        fn sub(self, rhs: V) -> Self::Output {
            Self::raw(sub_mod_raw(self.val, rhs.into().val, Self::modulus()))
        }
    }
    impl<V: Into<ModIntBase<M>>, M: Modulus> Mul<V> for ModIntBase<M> {
        type Output = Self;
        #[inline]
        fn mul(self, rhs: V) -> Self::Output {
            Self::raw(M::mul(self.val, rhs.into().val))
        }
    }
    impl<V: Into<ModIntBase<M>>, M: Modulus> Div<V> for ModIntBase<M> {
        type Output = Self;
        #[inline]
        fn div(self, rhs: V) -> Self::Output { self * rhs.into().inv() }
    }

    impl <V: Into<ModIntBase<M>>, M: Modulus> AddAssign<V> for ModIntBase<M> {
        #[inline]
        fn add_assign(&mut self, rhs: V) { *self = *self + rhs; }
    }
    impl <V: Into<ModIntBase<M>>, M: Modulus> SubAssign<V> for ModIntBase<M> {
        #[inline]
        fn sub_assign(&mut self, rhs: V) { *self = *self - rhs; }
    }
    impl <V: Into<ModIntBase<M>>, M: Modulus> MulAssign<V> for ModIntBase<M> {
        #[inline]
        fn mul_assign(&mut self, rhs: V) { *self = *self * rhs; }
    }
    impl <V: Into<ModIntBase<M>>, M: Modulus> DivAssign<V> for ModIntBase<M> {
        #[inline]
        fn div_assign(&mut self, rhs: V) { *self = *self / rhs; }
    }

    impl <M: Modulus> std::iter::Sum for ModIntBase<M> {
        #[inline] fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
            iter.fold(Self::raw(0), Add::add)
        }
    }
    impl <M: Modulus> std::iter::Product for ModIntBase<M> {
        #[inline] fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
            iter.fold(1.into(), Mul::mul)
        }
    }
    impl<'a, M: Modulus> std::iter::Sum<&'a Self> for ModIntBase<M> {
        #[inline] fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> ModIntBase<M> {
            iter.fold(Self::raw(0), |a, &b| a + b)
        }
    }
    impl<'a, M: Modulus> std::iter::Product<&'a Self> for ModIntBase<M> {
        #[inline] fn product<I: Iterator<Item = &'a Self>>(iter: I) -> ModIntBase<M> {
            iter.fold(1.into(), |a, &b| a * b)
        }
    }

    macro_rules! const_modulus {
        ($mint: ident, $name: ident, $modulus: expr) => {
            #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
            pub enum $name {}
            impl Modulus for $name {
                #[inline(always)] fn get_modulus() -> u32 { $modulus }
                fn mul(a: u32, b: u32) -> u32 {
                    mul_mod_u32(a, b, Self::get_modulus())
                }
            }
            pub type $mint = ModIntBase<$name>;
        }
    }

    #[derive(Debug, Clone, Copy)]
    pub struct ModulusCalc {
        pub modulus: u32,
        pub inv: u64
    }

    macro_rules! dynamic_modulus {
        ($mint: ident, $name: ident, $modulus: ident) => {
            static $modulus: crate::Unsync<Cell<ModulusCalc>> = crate::Unsync(Cell::new(ModulusCalc { modulus: 0, inv: 0 }));
            #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
            pub enum $name {}
            impl Modulus for $name {
                fn get_modulus() -> u32 { $modulus.0.get().modulus }
                fn mul(a: u32, b: u32) -> u32 {
                    let ModulusCalc { modulus, inv } = $modulus.0.get();
                    let p = a as u64 * b as u64;
                    let g = ((p as u128 * inv as u128) >> 64) as u64;
                    let (r, c) = p.overflowing_sub(g * modulus as u64);
                    if c { (r as u32).wrapping_add(modulus) } else { r as u32 }
                }
            }
            impl $name {
                pub fn set_modulus(val: u32) {
                    let inv = (1u64.wrapping_neg() / val as u64).wrapping_add(1);
                    $modulus.0.set(ModulusCalc { modulus: val, inv })
                }
            }
            pub type $mint = ModIntBase<$name>;
        }
    }

    const_modulus!(ModInt998_244_353, Mod998_244_353, 998_244_353);
    const_modulus!(ModInt1_000_000_007, Mod1_000_000_007, 1_000_000_007);
    dynamic_modulus!(DynamicModInt, DynamicModulus, DYNAMIC_MODULUS);
}

use crate::modint::*;
// type ModInt = ModInt998_244_353;
type ModInt = ModInt1_000_000_007;
// const_modulus!(ModInt, DefaultModulus, 1_000_000_009);
// type ModInt = DynamicModInt;

fn mod_factorials(maxn: usize) -> Vec<ModInt> {
    let mut res = vec![ModInt::default(); maxn+1];
    res[0] = 1.into();
    for i in 1..=maxn {
        res[i] = res[i-1] * i
    }
    return res;
}

struct ModCombinatorics {
    factorials: Vec<ModInt>,
    inv_factorials: Vec<ModInt>
}
#[allow(non_snake_case)]
impl ModCombinatorics {
    fn new(maxn: usize) -> Self {
        let factorials = mod_factorials(maxn);
        let mut inv = vec![ModInt::default(); maxn+1];
        inv[maxn] = factorials[maxn].inv();
        for i in (1..=maxn).rev() {
            inv[i-1] = inv[i] * i;
        }
        Self { factorials, inv_factorials: inv }
    }
    #[inline]
    fn factorial(&self, n: usize) -> ModInt { self.factorials[n] }
    #[inline]
    fn inv_factorial(&self, n: usize) -> ModInt { self.inv_factorials[n] }
    fn P(&self, n: usize, k: usize) -> ModInt {
        if k > n { ModInt::raw(0) } else { self.factorial(n) * self.inv_factorial(n-k) }
    }
    fn C(&self, n: usize, k: usize) -> ModInt {
        if k > n { ModInt::raw(0) } else { self.factorial(n) * self.inv_factorial(k) * self.inv_factorial(n-k) }
    }

    // multi-choose, be sure to adjust maxn accordingly
    fn M(&self, n: usize, k: usize) -> ModInt {
        if k == 0 { 1.into() } else { self.C(n + k - 1, k) }
    }
}

#[allow(non_snake_case, non_upper_case_globals)]
fn main() {
    let num_cases: usize = 1;//read();

    for _case_num in 1..=num_cases {
        let n = read!(usize);
        let k = read!(usize);
        let mc = ModCombinatorics::new(n);

        let ans = (0..=min(n, k)).map(|i| mc.inv_factorial(i) * mc.inv_factorial(n-i)).sum::<ModInt>() * mc.factorial(n);
        println!(ans);
    }

    out_flush();
}

use std::{io::{BufRead, BufWriter, Write}, hash::Hash};
#[allow(unused)]
use std::{{collections::*, mem::swap},cmp::Reverse};

use std::convert::TryInto;

pub struct Combi<const MOD:usize> {
    fact: Vec<usize>,
    ifact: Vec<usize>,
}
impl <const MOD:usize> Combi<MOD> {
    pub fn new(n:usize) -> Self{
        let mut fact = vec![0;n+1];
        fact[0]=1;
        for i in 0..n {
            fact[i+1] = fact[i]*(i+1)%MOD;
        }
        let mut ifact = vec![0;n+1];
        ifact[n] = Self::inv(fact[n]);
        for i in (0..n).rev() {
            ifact[i] = ifact[i+1]*(i+1)%MOD;
        }
        return Self { fact, ifact};
    }

    pub fn kperm<U: TryInto<usize>>(&self,n:U,k:U) -> usize {
        let n = n.try_into().ok().expect("Unable to cast n to usize");
        let k = k.try_into().ok().expect("Unable to cast k to usize");
        if n < k {
            return 0;
        }
        return self.fact[n]*self.ifact[n-k]%MOD;
    }

    pub fn kcombi<U: TryInto<usize>>(&self,n:U,k:U) -> usize {
        let n = n.try_into().ok().expect("Unable to cast n to usize");
        let k = k.try_into().ok().expect("Unable to cast k to usize");
        if n < k {
            return 0;
        }
        return self.fact[n]*self.ifact[k]%MOD*self.ifact[n-k]%MOD;
    }

    pub fn fact(&self) -> &Vec<usize> { &self.fact }
    pub fn ifact(&self) -> &Vec<usize> { &self.ifact }

    fn pow(val:usize, mut power: usize) -> usize {
        let mut square = val;
        let mut ret = 1;
        while 0 < power {
            if (power & 1) == 1{
                ret *= square;
                ret %= MOD;
            }
            square *= square;
            square %= MOD;
            power >>= 1;
        }
        return ret;
    }
    fn inv(val: usize) -> usize {
        return Self::pow(val, MOD - 2);
    }
}

impl <const MOD:usize> Default for Combi<MOD>{
    fn default() -> Self {
        return Self::new(1_000_000);
    }
}

fn main() {
    let sin = std::io::stdin();
    let scan = &mut Scanner::new(sin.lock());
    let sout = std::io::stdout();
    let out = &mut BufWriter::new(sout.lock());
    solve_wrapper(scan, out, solve);
}

#[allow(unused)]
#[macro_export]
macro_rules! logln {
    ($($arg:tt)*) => ({
        #[cfg(debug_assertions)]
        println!($($arg)*);
    })
}

trait MapX<K,V:Default> {
    fn update_with<F: FnOnce(&mut V) -> V>(&mut self, key:K, get_new_value:F);
}
macro_rules! update_with { () => {
    fn update_with<F: FnOnce(&mut V) -> V>(&mut self, key:K, get_new_value:F) {
        let v = self.entry(key).or_default();
        let nv = get_new_value(v);
        *v = nv;
    }
} }
impl <K:Ord,V:Default> MapX<K,V> for BTreeMap<K,V> {
    update_with!();
}
impl <K:Hash+Eq,V:Default> MapX<K,V> for HashMap<K,V> {
    update_with!();
}

trait UsizeX {
    fn i64(self) -> i64;
    fn ssb(self,rhs:usize) -> usize;
}
impl UsizeX for usize {
    fn i64(self) -> i64 { self as i64 }
    fn ssb(self,rhs:usize) -> usize { self.saturating_sub(rhs) }
}

trait I64X {
    fn usize(self) -> usize; }
impl I64X for i64 {
    fn usize(self) -> usize { self as usize }
}

pub struct Scanner<R> {
    reader: R,
    buffer: Vec<String>,
}
impl<R: ::std::io::BufRead> Scanner<R> {
    pub fn new(reader: R) -> Self {
        Self { reader, buffer: vec![] }
    }
    pub fn token<T: ::std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop() {
                return token.parse().ok().expect("Failed parse");
            }
            let mut input = String::new();
            self.reader.read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
    pub fn line<T: ::std::str::FromStr>(&mut self) -> Vec<T> {
        if !self.buffer.is_empty() {
            panic!("Consume token buffer before read a line.");
        }
        let mut input = String::new();
        self.reader.read_line(&mut input).expect("Failed read");
        input.split_whitespace().map(|v| v.parse().ok().expect("Failed parse")).collect()
    }
    pub fn line_with<T: ::std::str::FromStr,F: FnMut(&T)->T>(&mut self, f: F) -> Vec<T> {
        return self.line().iter().map(f).collect::<Vec<_>>();
    }
}

#[cfg(test)]
mod abc999x {
    use super::*;
    use std::io::Read;

    macro_rules! test_macro {
        ($name:ident,) => {
            #[test]
            fn $name() {
                let fn_name = stringify!($name);
                let test_no = fn_name.as_bytes().last().copied().unwrap() as char;
                let bname = env!("CARGO_BIN_NAME");
                let fname = format!("src/contest/{}/in{}",bname,test_no);
                let f = std::fs::File::open(fname);
                if f.is_err() {
                    panic!("No input file");
                }
                let mut f = f.unwrap();
                let mut inp = Vec::new();
                f.read_to_end(&mut inp).unwrap();
                let fname = format!("src/contest/{}/out{}",bname,test_no);
                let f = std::fs::File::open(fname);
                let mut exp = Vec::new();
                if let Ok(mut f) = f {
                    f.read_to_end(&mut exp).unwrap();
                }
                let exp = String::from_utf8_lossy(&exp);
                let out = &mut Vec::new();
                let scan = &mut Scanner::new(&*inp);
                solve_wrapper(scan, out, solve);
                let out = String::from_utf8_lossy(&out);
                assert_eq!(exp, out);
            }
        };
        ($name:ident, $($n:ident),*,) => {
            test_macro!($name,);
            test_macro!($($n),*,);
        };
    }

    test_macro!(
test1,
test2,
test3,
);

}

fn solve_wrapper<B,W,F>(scan: &mut Scanner<B>, out: &mut W, mut solve: F)
    where B: BufRead, W: Write, F:FnMut(&mut Scanner<B>, &mut W)
    {
    let t = 1;
    //let t = scan.token::<usize>();
    for _ in 0..t {
        solve(scan,out);
    }
}

const MOD:usize = 1e9 as usize + 7;

fn solve(scan: &mut Scanner<impl BufRead>, out: &mut impl Write) {
    let n = scan.token::<usize>();
    let k = scan.token::<usize>();
    let cmb = Combi::<MOD>::new(n);
    cmb.kcombi(n,k);
    let mut ans = 0;
    for i in 0..(k.min(n)+1) {
        ans+=cmb.kcombi(n,i);
        ans%=MOD;
    }
    writeln!(out, "{}", ans).ok();
}

// ---------- begin scanner -----------
#[allow(unused_imports)]
use std::io::{BufWriter, stdin, stdout, Read, Write, Stdout};
use std::str::FromStr;

pub struct Scanner<'a> {
    it: std::str::SplitWhitespace<'a>,
}
#[allow(dead_code)]
impl<'a> Scanner<'a> {
    pub fn new(s: &'a String) -> Scanner<'a> {
        Scanner {
            it: s.split_whitespace(),
        }
    }
    pub fn next<T: FromStr>(&mut self) -> T {
        self.it.next().expect("read EOF").parse::<T>().ok().expect("parse failed")
    }
    pub fn next_n<T: FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.next()).collect()
    }
    pub fn next_n_index1<T: FromStr + Default>(&mut self, n: usize) -> Vec<T> {
        std::iter::once(T::default()).chain((0..n).map(|_| self.next())).collect()
    }
    pub fn next_chars(&mut self) -> Vec<char> { self.it.next().unwrap().chars().collect() }
    pub fn next_bytes(&mut self) -> Vec<u8> { self.it.next().unwrap().bytes().collect() }
    pub fn next_digits(&mut self) -> Vec<u8> {
        self.it.next().unwrap().bytes().map(|c|c-C0).collect()
    }
}
// ---------- end scanner -------------

// ---------- begin utils -------------
#[allow(dead_code)]
const C0: u8 = '0' as u8;

// ---------- end utils ---------------

// ---------- begin debugger ----------
#[cfg(feature = "my_debug")]
#[macro_export]
macro_rules! debug {
    () => {
        eprintln!("[{}:{}]", file!(), line!())
    };
    ($val:expr $(,)?) => {
        eprintln!("[{}:{}] {} = {:?}", file!(), line!(), stringify!($val), &($val))
    };
    ($($val:expr),+ $(,)?) => {
        ($(debug!($val)),+,)
    };
}

#[cfg(not(feature = "my_debug"))]
#[macro_export]
macro_rules! debug {
    ($( $args:expr ),*) => {}
}
// ---------- end debugger ------------

fn main() {
    debug!("Ish: good luck and high rating!");

    #[cfg(not(feature = "my_debug"))]
        let s = {
        let mut s = String::new();
        stdin().read_to_string(&mut s).unwrap();
        s
    };
    #[cfg(feature = "my_debug")]
        let s = std::fs::read_to_string("in.txt").unwrap();

    let mut sc = Scanner::new(&s);
    let out = &mut BufWriter::new(stdout());

    // let cases: u32 = sc.next();
    let cases: u32 = 1;
    debug!(cases);
    for _case in 1..=cases { debug!(_case);
        run(&mut sc, out);
    }
}

/** Write your mind here.
1234 -
不妨假设都是左赢
1
1  3
12 34
3142

1
1     5
1  3  5  7
12 34 56 78

1
1     2
1 3   2  4
153

1 一定不能和

二分？
1
1    3
1 2   3  4
15  26 37 48

1
1   2
1   3    2 5
14  36    27 58

简单的说，1 有被每个对手替换的风险。
如果 k=1，答案就是 n+1，因为 1 可能被三个对手替换，从中选择最菜的。

如果 k=2 呢， 可以替换两次。

1~16, k=1, ans=5
k=2, 可以换的就是

1
1           9
1     5     9     d
1  3  5  7  9  b  d  f
1_ _+ _+ +8 _+ +c +e f0

*可以换多少个
k=0, 1
k=1, n个,            4
k=2，1+2+..+n-1,     7
k=3,   1

层
0: n
1: 1, 2, 3, 4, .., n-1
2:

n^2 做法有了，层数转移。

原数组
0 0 0 0 1    k=0, ans=1
1 1 1 1 0    k=1, ans=4
3 2 1 0 0    k=2, ans=7
3 1 0 0 0    k=3, ans=8
1 0 0 0 0    k=4, ans=8

n=3

ans(n, k) = for i in 0..=k {
    C(n, i)
}

 */

struct MathSolver {
    fac: Vec<i64>,
}
impl MathSolver {
    const MOD: i64 = 1000000007;

    fn new(mx: usize) -> Self {
        let mut fac = vec![1i64; mx];
        for i in 1..mx {
            fac[i] = (fac[i-1] * i as i64) % Self::MOD;
        }
        Self { fac }
    }

    // solve ax+by=gcd(a,b)
    fn exgcd(a: i64, b: i64) -> (i64, i64) {
        if b == 0 {
            return (1, 0);
        }
        let (x, y) = Self::exgcd(b, a % b);
        (y, x - a / b * y)
    }

    fn normalize(a: i64) -> i64 {
        (a % Self::MOD + Self::MOD) % Self::MOD
    }

    // solve ax===1 (mod b)
    fn inv(&self, a: i64) -> i64{
        Self::normalize(Self::exgcd(a, Self::MOD).0)
    }

    fn c(&self, a: usize, b: usize) -> i64 {
        self.fac[a] * self.inv(self.fac[b] * self.fac[a-b] % Self::MOD) % Self::MOD
    }
}

fn run(sc: &mut Scanner, out: &mut BufWriter<Stdout>) {
    let n = sc.next::<usize>();
    let k = sc.next::<usize>();

    let solver = MathSolver::new(n+1);
    let mut ans = 0;
    for i in 0..=k.min(n) {
        ans += solver.c(n, i);
        ans %= 1_000_000_007;
    }

    // let ans = if arr == brr {"YES"} else {"NO"};

    // let ans = 1;
    // let mut ok = true;
    // let ans = if ok {"Yes"} else {"No"};
    writeln!(out, "{ans}").ok();
    // for ans in ans {
    //     for num in ans { write!(out, "{num}").ok(); }
    //     writeln!(out).ok();
    // }
}

type Mod = ModInt1000000007;
fn main() {
    let stdout = std::io::stdout();
    let mut writer = std::io::BufWriter::new(stdout.lock());
    #[allow(unused_macros)] macro_rules! print { ($($tt:tt)*) => {{ use std::io::Write; std::write!(writer, $($tt)*).unwrap(); }}; }
    #[allow(unused_macros)] macro_rules! println { ($($tt:tt)*) => {{ use std::io::Write; std::writeln!(writer, $($tt)*).unwrap(); }}; }

    let mut precalc = Binom::<Mod>::new();
    input! {
        n: usize,
        k: usize
    }
    let k = k.min(n);
    let mut ans = Mod::raw(0);
    for i in 0..=k {
        ans += precalc.binom(n, i);
    }
    println!("{}", ans);
}

struct Binom<T> {
    len: usize,
    inv: Vec<usize>,
    fact: Vec<T>,
    ifact: Vec<T>,
    n: Option<usize>,
    nprod: Vec<T>,
    m: Option<usize>,
    mprod_n: usize,
    mprod: T
}

#[allow(dead_code)]
impl<T: ModIntBase + std::iter::Product> Binom<T> {
    pub fn new() -> Self {
        assert_eq!(std::mem::size_of::<usize>(), 8);

        Self {
            len: 1,
            inv: vec![0, 1],
            fact: vec![T::raw(1), T::raw(1)],
            ifact: vec![T::raw(1), T::raw(1)],
            n: None,
            nprod: vec![],
            m: None,
            mprod_n: 0,
            mprod: T::raw(0)
        }
    }

    fn ensure(&mut self, idx: usize) {
        if idx > self.len {
            self.inv.reserve(idx - self.len);
            self.fact.reserve(idx - self.len);
            self.ifact.reserve(idx - self.len);
            let m = T::modulus() as usize;
            for i in self.len+1..=idx {
                let inv_i = self.inv[m % i] * (m - m / i) % m;
                self.inv.push(inv_i);
                self.fact.push(self.fact[i - 1] * T::from(i));
                self.ifact.push(self.ifact[i - 1] * T::raw(inv_i as u32));
            }
            self.len = idx;
        }
    }

    pub fn binom(&mut self, n: usize, m: usize) -> T {
        if m > n {
            return T::raw(0)
        }
        if m == 0 || m == n {
            return T::raw(1)
        }
        self.ensure(n);
        self.fact[n] * self.ifact[m] * self.ifact[n - m]
    }

    pub fn binom_n(&mut self, n: usize, m: usize) -> T {
        if m > n {
            return T::raw(0)
        }
        if m == 0 || m == n {
            return T::raw(1)
        }
        if n >= T::modulus() as usize {
            return self.binom_n(n % T::modulus() as usize, m);
        }
        if self.n != Some(n) {
            self.n = Some(n);
            self.nprod = vec![T::from(n)];
        }
        for i in self.nprod.len()..m {
            self.nprod.push(self.nprod[i - 1] * T::from(n - i));
        }
        self.ensure(m);
        self.nprod[m - 1] * self.ifact[m]
    }

    pub fn binom_m(&mut self, n: usize, m: usize) -> T {
        if m > n {
            return T::raw(0)
        }
        if m == 0 || m == n {
            return T::raw(1)
        }
        if n >= T::modulus() as usize {
            return self.binom_m(n % T::modulus() as usize, m);
        }
        if self.m != Some(m) || self.mprod_n > n + m || self.mprod_n + m < n {
            self.m = Some(m);
            self.mprod_n = n;
            self.mprod = ((n-m+1)..=n).map(T::from).product::<T>();
        } else {
            while self.mprod_n < n {
                self.mprod_n += 1;
                self.mprod *= T::from(self.mprod_n);
                self.mprod /= T::from(self.mprod_n - m);
            }
            while self.mprod_n > n {
                self.mprod /= T::from(self.mprod_n);
                self.mprod *= T::from(self.mprod_n - m);
                self.mprod_n -= 1;
            }
        }
        self.ensure(m);
        self.mprod * self.ifact[m]
    }

}

// input macro with modifications (to better align with proconio)
// based on https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8

#[macro_export]
macro_rules! input {
    (@lock_stdin $reader:ident) => {
        let stdin = std::io::stdin();
        let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
        let mut $reader = move || -> String {
            unsafe {
                String::from_utf8_unchecked(
                    bytes
                        .by_ref()
                        .map_while(Result::ok)
                        .skip_while(|c| c.is_ascii_whitespace())
                        .take_while(|c| !c.is_ascii_whitespace())
                        .collect()
                )
            }
        };
    };

    (@inner $reader:ident) => {};
    (@inner $reader:ident, ) => {};

    (@inner $reader:ident, mut $var:ident : $t:tt $($r:tt)*) => {
        let mut $var = read_value!($reader, $t);
        input!{@inner $reader $($r)*}
    };

    (@inner $reader:ident, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($reader, $t);
        input!{@inner $reader $($r)*}
    };

    (@inner $reader:ident $($r:tt)*) => {
        compile_error!(stringify!(unable to read $($r)*))
    };

    (line = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_ascii_whitespace();
        let mut next = || { iter.next().unwrap_or_default() };
        input!{@inner next, $($r)*}
    };
    (name = $reader:ident, $($r:tt)*) => {
        input!{@lock_stdin $reader};
        input!{@inner $reader, $($r)*}
    };
    (use $reader:ident, $($r:tt)*) => {
        input!{@inner $reader, $($r)*}
    };
    ($($r:tt)*) => {
        input!{@lock_stdin reader};
        input!{@inner reader, $($r)*};
    };
}

#[macro_export]
macro_rules! read_value {
    ($reader:ident, ( $($t:tt),* )) => {
        ( $(read_value!($reader, $t)),* )
    };

    ($reader:ident, [ $t:tt ]) => {{
        let len = read_value!($reader, usize);
        read_value!($reader, [ $t ; len])
    }};

    ($reader:ident, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($reader, $t)).collect::<Vec<_>>()
    };

    ($reader:ident, chars) => {
        read_value!($reader, String).chars().collect::<Vec<char>>()
    };

    ($reader:ident, bytes) => {
        read_value!($reader, String).into_bytes()
    };

    ($reader:ident, usize1) => {
        read_value!($reader, usize) - 1
    };

    ($reader:ident, $t:tt) => {
        $reader().parse::<$t>().expect(stringify!(parse error($t)))
    };
}

//https://github.com/rust-lang-ja/ac-library-rs

pub mod internal_math {
    #![allow(dead_code)]
    use std::mem::swap;

    pub(crate) fn safe_mod(mut x: i64, m: i64) -> i64 {
        x %= m;
        if x < 0 {
            x += m;
        }
        x
    }

    pub(crate) struct Barrett {
        pub(crate) _m: u32,
        pub(crate) im: u64,
    }

    impl Barrett {
        pub(crate) fn new(m: u32) -> Barrett {
            Barrett {
                _m: m,
                im: (-1i64 as u64 / m as u64).wrapping_add(1),
            }
        }

        pub(crate) fn umod(&self) -> u32 {
            self._m
        }

        #[allow(clippy::many_single_char_names)]
        pub(crate) fn mul(&self, a: u32, b: u32) -> u32 {
            mul_mod(a, b, self._m, self.im)
        }
    }

    #[allow(clippy::many_single_char_names)]
    pub(crate) fn mul_mod(a: u32, b: u32, m: u32, im: u64) -> u32 {
        let mut z = a as u64;
        z *= b as u64;
        let x = (((z as u128) * (im as u128)) >> 64) as u64;
        let mut v = z.wrapping_sub(x.wrapping_mul(m as u64)) as u32;
        if m <= v {
            v = v.wrapping_add(m);
        }
        v
    }

    #[allow(clippy::many_single_char_names)]
    pub(crate) fn pow_mod(x: i64, mut n: i64, m: i32) -> i64 {
        if m == 1 {
            return 0;
        }
        let _m = m as u32;
        let mut r: u64 = 1;
        let mut y: u64 = safe_mod(x, m as i64) as u64;
        while n != 0 {
            if (n & 1) > 0 {
                r = (r * y) % (_m as u64);
            }
            y = (y * y) % (_m as u64);
            n >>= 1;
        }
        r as i64
    }

    pub(crate) fn is_prime(n: i32) -> bool {
        let n = n as i64;
        match n {
            _ if n <= 1 => return false,
            2 | 7 | 61 => return true,
            _ if n % 2 == 0 => return false,
            _ => {}
        }
        let mut d = n - 1;
        while d % 2 == 0 {
            d /= 2;
        }
        for &a in &[2, 7, 61] {
            let mut t = d;
            let mut y = pow_mod(a, t, n as i32);
            while t != n - 1 && y != 1 && y != n - 1 {
                y = y * y % n;
                t <<= 1;
            }
            if y != n - 1 && t % 2 == 0 {
                return false;
            }
        }
        true
    }

    #[allow(clippy::many_single_char_names)]
    pub(crate) fn inv_gcd(a: i64, b: i64) -> (i64, i64) {
        let a = safe_mod(a, b);
        if a == 0 {
            return (b, 0);
        }

        let mut s = b;
        let mut t = a;
        let mut m0 = 0;
        let mut m1 = 1;

        while t != 0 {
            let u = s / t;
            s -= t * u;
            m0 -= m1 * u; // |m1 * u| <= |m1| * s <= b

            swap(&mut s, &mut t);
            swap(&mut m0, &mut m1);
        }
        if m0 < 0 {
            m0 += b / s;
        }
        (s, m0)
    }

    pub(crate) fn primitive_root(m: i32) -> i32 {
        match m {
            2 => return 1,
            167_772_161 => return 3,
            469_762_049 => return 3,
            754_974_721 => return 11,
            998_244_353 => return 3,
            _ => {}
        }

        let mut divs = [0; 20];
        divs[0] = 2;
        let mut cnt = 1;
        let mut x = (m - 1) / 2;
        while x % 2 == 0 {
            x /= 2;
        }
        for i in (3..std::i32::MAX).step_by(2) {
            if i as i64 * i as i64 > x as i64 {
                break;
            }
            if x % i == 0 {
                divs[cnt] = i;
                cnt += 1;
                while x % i == 0 {
                    x /= i;
                }
            }
        }
        if x > 1 {
            divs[cnt] = x;
            cnt += 1;
        }
        let mut g = 2;
        loop {
            if (0..cnt).all(|i| pow_mod(g, ((m - 1) / divs[i]) as i64, m) != 1) {
                break g as i32;
            }
            g += 1;
        }
    }
}
pub mod modint {

    use crate::internal_math;
    use std::{
        cell::RefCell,
        convert::{Infallible, TryInto as _},
        fmt,
        hash::{Hash, Hasher},
        iter::{Product, Sum},
        marker::PhantomData,
        ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
        str::FromStr,
        sync::atomic::{self, AtomicU32, AtomicU64},
        thread::LocalKey,
    };

    pub type ModInt1000000007 = StaticModInt<Mod1000000007>;
    pub type ModInt998244353 = StaticModInt<Mod998244353>;
    pub type ModInt = DynamicModInt<DefaultId>;

    #[derive(Copy, Clone, Eq, PartialEq)]
    #[repr(transparent)]
    pub struct StaticModInt<M> {
        val: u32,
        phantom: PhantomData<fn() -> M>,
    }

    impl<M: Modulus> StaticModInt<M> {
        #[inline(always)]
        pub fn modulus() -> u32 {
            M::VALUE
        }

        #[inline]
        pub fn new<T: RemEuclidU32>(val: T) -> Self {
            Self::raw(val.rem_euclid_u32(M::VALUE))
        }

        #[inline]
        pub fn raw(val: u32) -> Self {
            Self {
                val,
                phantom: PhantomData,
            }
        }

        #[inline]
        pub fn val(self) -> u32 {
            self.val
        }

        #[inline]
        pub fn pow(self, n: u64) -> Self {
            <Self as ModIntBase>::pow(self, n)
        }

        #[inline]
        pub fn inv(self) -> Self {
            if M::HINT_VALUE_IS_PRIME {
                if self.val() == 0 {
                    panic!("attempt to divide by zero");
                }
                debug_assert!(
                    internal_math::is_prime(M::VALUE.try_into().unwrap()),
                    "{} is not a prime number",
                    M::VALUE,
                );
                self.pow((M::VALUE - 2).into())
            } else {
                Self::inv_for_non_prime_modulus(self)
            }
        }
    }

    impl<M: Modulus> ModIntBase for StaticModInt<M> {
        #[inline(always)]
        fn modulus() -> u32 {
            Self::modulus()
        }

        #[inline]
        fn raw(val: u32) -> Self {
            Self::raw(val)
        }

        #[inline]
        fn val(self) -> u32 {
            self.val()
        }

        #[inline]
        fn inv(self) -> Self {
            self.inv()
        }
    }

    pub trait Modulus: 'static + Copy + Eq {
        const VALUE: u32;
        const HINT_VALUE_IS_PRIME: bool;

        fn butterfly_cache() -> &'static LocalKey<RefCell<Option<ButterflyCache<Self>>>>;
    }

    #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
    pub enum Mod1000000007 {}

    impl Modulus for Mod1000000007 {
        const VALUE: u32 = 1_000_000_007;
        const HINT_VALUE_IS_PRIME: bool = true;

        fn butterfly_cache() -> &'static LocalKey<RefCell<Option<ButterflyCache<Self>>>> {
            thread_local! {
                static BUTTERFLY_CACHE: RefCell<Option<ButterflyCache<Mod1000000007>>> = RefCell::default();
            }
            &BUTTERFLY_CACHE
        }
    }

    #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
    pub enum Mod998244353 {}

    impl Modulus for Mod998244353 {
        const VALUE: u32 = 998_244_353;
        const HINT_VALUE_IS_PRIME: bool = true;

        fn butterfly_cache() -> &'static LocalKey<RefCell<Option<ButterflyCache<Self>>>> {
            thread_local! {
                static BUTTERFLY_CACHE: RefCell<Option<ButterflyCache<Mod998244353>>> = RefCell::default();
            }
            &BUTTERFLY_CACHE
        }
    }

    #[allow(dead_code)]
    pub struct ButterflyCache<M> {
        pub(crate) sum_e: Vec<StaticModInt<M>>,
        pub(crate) sum_ie: Vec<StaticModInt<M>>,
    }

    #[derive(Copy, Clone, Eq, PartialEq)]
    #[repr(transparent)]
    pub struct DynamicModInt<I> {
        val: u32,
        phantom: PhantomData<fn() -> I>,
    }

    impl<I: Id> DynamicModInt<I> {
        #[inline]
        pub fn modulus() -> u32 {
            I::companion_barrett().umod()
        }

        #[inline]
        pub fn set_modulus(modulus: u32) {
            if modulus == 0 {
                panic!("the modulus must not be 0");
            }
            I::companion_barrett().update(modulus);
        }

        #[inline]
        pub fn new<T: RemEuclidU32>(val: T) -> Self {
            <Self as ModIntBase>::new(val)
        }

        #[inline]
        pub fn raw(val: u32) -> Self {
            Self {
                val,
                phantom: PhantomData,
            }
        }

        #[inline]
        pub fn val(self) -> u32 {
            self.val
        }

        #[inline]
        pub fn pow(self, n: u64) -> Self {
            <Self as ModIntBase>::pow(self, n)
        }

        #[inline]
        pub fn inv(self) -> Self {
            Self::inv_for_non_prime_modulus(self)
        }
    }

    impl<I: Id> ModIntBase for DynamicModInt<I> {
        #[inline]
        fn modulus() -> u32 {
            Self::modulus()
        }

        #[inline]
        fn raw(val: u32) -> Self {
            Self::raw(val)
        }

        #[inline]
        fn val(self) -> u32 {
            self.val()
        }

        #[inline]
        fn inv(self) -> Self {
            self.inv()
        }
    }

    pub trait Id: 'static + Copy + Eq {
        fn companion_barrett() -> &'static Barrett;
    }

    #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
    pub enum DefaultId {}

    impl Id for DefaultId {
        fn companion_barrett() -> &'static Barrett {
            static BARRETT: Barrett = Barrett::default();
            &BARRETT
        }
    }

    pub struct Barrett {
        m: AtomicU32,
        im: AtomicU64,
    }

    impl Barrett {
        #[inline]
        pub const fn new(m: u32) -> Self {
            Self {
                m: AtomicU32::new(m),
                im: AtomicU64::new((-1i64 as u64 / m as u64).wrapping_add(1)),
            }
        }

        #[inline]
        const fn default() -> Self {
            Self::new(998_244_353)
        }

        #[inline]
        fn update(&self, m: u32) {
            let im = (-1i64 as u64 / m as u64).wrapping_add(1);
            self.m.store(m, atomic::Ordering::SeqCst);
            self.im.store(im, atomic::Ordering::SeqCst);
        }

        #[inline]
        fn umod(&self) -> u32 {
            self.m.load(atomic::Ordering::SeqCst)
        }

        #[inline]
        fn mul(&self, a: u32, b: u32) -> u32 {
            let m = self.m.load(atomic::Ordering::SeqCst);
            let im = self.im.load(atomic::Ordering::SeqCst);
            internal_math::mul_mod(a, b, m, im)
        }
    }

    impl Default for Barrett {
        #[inline]
        fn default() -> Self {
            Self::default()
        }
    }

    pub trait ModIntBase:
        Default
        + FromStr
        + From<i8>
        + From<i16>
        + From<i32>
        + From<i64>
        + From<i128>
        + From<isize>
        + From<u8>
        + From<u16>
        + From<u32>
        + From<u64>
        + From<u128>
        + From<usize>
        + Copy
        + Eq
        + Hash
        + fmt::Display
        + fmt::Debug
        + Neg<Output = Self>
        + Add<Output = Self>
        + Sub<Output = Self>
        + Mul<Output = Self>
        + Div<Output = Self>
        + AddAssign
        + SubAssign
        + MulAssign
        + DivAssign
    {
        fn modulus() -> u32;

        fn raw(val: u32) -> Self;

        fn val(self) -> u32;

        fn inv(self) -> Self;

        #[inline]
        fn new<T: RemEuclidU32>(val: T) -> Self {
            Self::raw(val.rem_euclid_u32(Self::modulus()))
        }

        #[inline]
        fn pow(self, mut n: u64) -> Self {
            let mut x = self;
            let mut r = Self::raw(1);
            while n > 0 {
                if n & 1 == 1 {
                    r *= x;
                }
                x *= x;
                n >>= 1;
            }
            r
        }
    }

    pub trait RemEuclidU32 {
        fn rem_euclid_u32(self, modulus: u32) -> u32;
    }

    macro_rules! impl_rem_euclid_u32_for_small_signed {
    ($($ty:tt),*) => {
        $(
            impl RemEuclidU32 for $ty {
                #[inline]
                fn rem_euclid_u32(self, modulus: u32) -> u32 {
                    (self as i64).rem_euclid(i64::from(modulus)) as _
                }
            }
        )*
    }
}

    impl_rem_euclid_u32_for_small_signed!(i8, i16, i32, i64, isize);

    impl RemEuclidU32 for i128 {
        #[inline]
        fn rem_euclid_u32(self, modulus: u32) -> u32 {
            self.rem_euclid(i128::from(modulus)) as _
        }
    }

    macro_rules! impl_rem_euclid_u32_for_small_unsigned {
    ($($ty:tt),*) => {
        $(
            impl RemEuclidU32 for $ty {
                #[inline]
                fn rem_euclid_u32(self, modulus: u32) -> u32 {
                    self as u32 % modulus
                }
            }
        )*
    }
}

    macro_rules! impl_rem_euclid_u32_for_large_unsigned {
    ($($ty:tt),*) => {
        $(
            impl RemEuclidU32 for $ty {
                #[inline]
                fn rem_euclid_u32(self, modulus: u32) -> u32 {
                    (self % (modulus as $ty)) as _
                }
            }
        )*
    }
}

    impl_rem_euclid_u32_for_small_unsigned!(u8, u16, u32);
    impl_rem_euclid_u32_for_large_unsigned!(u64, u128);

    #[cfg(target_pointer_width = "32")]
    impl_rem_euclid_u32_for_small_unsigned!(usize);

    #[cfg(target_pointer_width = "64")]
    impl_rem_euclid_u32_for_large_unsigned!(usize);

    trait InternalImplementations: ModIntBase {
        #[inline]
        fn inv_for_non_prime_modulus(this: Self) -> Self {
            let (gcd, x) = internal_math::inv_gcd(this.val().into(), Self::modulus().into());
            if gcd != 1 {
                panic!("the multiplicative inverse does not exist");
            }
            Self::new(x)
        }

        #[inline]
        fn default_impl() -> Self {
            Self::raw(0)
        }

        #[inline]
        fn from_str_impl(s: &str) -> Result<Self, Infallible> {
            Ok(s.parse::<i64>()
                .map(Self::new)
                .unwrap_or_else(|_| todo!("parsing as an arbitrary precision integer?")))
        }

        #[inline]
        fn hash_impl(this: &Self, state: &mut impl Hasher) {
            this.val().hash(state)
        }

        #[inline]
        fn display_impl(this: &Self, f: &mut fmt::Formatter) -> fmt::Result {
            fmt::Display::fmt(&this.val(), f)
        }

        #[inline]
        fn debug_impl(this: &Self, f: &mut fmt::Formatter) -> fmt::Result {
            fmt::Debug::fmt(&this.val(), f)
        }

        #[inline]
        fn neg_impl(this: Self) -> Self {
            Self::sub_impl(Self::raw(0), this)
        }

        #[inline]
        fn add_impl(lhs: Self, rhs: Self) -> Self {
            let modulus = Self::modulus();
            let mut val = lhs.val() + rhs.val();
            if val >= modulus {
                val -= modulus;
            }
            Self::raw(val)
        }

        #[inline]
        fn sub_impl(lhs: Self, rhs: Self) -> Self {
            let modulus = Self::modulus();
            let mut val = lhs.val().wrapping_sub(rhs.val());
            if val >= modulus {
                val = val.wrapping_add(modulus)
            }
            Self::raw(val)
        }

        fn mul_impl(lhs: Self, rhs: Self) -> Self;

        #[inline]
        fn div_impl(lhs: Self, rhs: Self) -> Self {
            Self::mul_impl(lhs, rhs.inv())
        }
    }

    impl<M: Modulus> InternalImplementations for StaticModInt<M> {
        #[inline]
        fn mul_impl(lhs: Self, rhs: Self) -> Self {
            Self::raw((u64::from(lhs.val()) * u64::from(rhs.val()) % u64::from(M::VALUE)) as u32)
        }
    }

    impl<I: Id> InternalImplementations for DynamicModInt<I> {
        #[inline]
        fn mul_impl(lhs: Self, rhs: Self) -> Self {
            Self::raw(I::companion_barrett().mul(lhs.val, rhs.val))
        }
    }

    macro_rules! impl_basic_traits {
    () => {};
    (impl <$generic_param:ident : $generic_param_bound:tt> _ for $self:ty; $($rest:tt)*) => {
        impl <$generic_param: $generic_param_bound> Default for $self {
            #[inline]
            fn default() -> Self {
                Self::default_impl()
            }
        }

        impl <$generic_param: $generic_param_bound> FromStr for $self {
            type Err = Infallible;

            #[inline]
            fn from_str(s: &str) -> Result<Self, Infallible> {
                Self::from_str_impl(s)
            }
        }

        impl<$generic_param: $generic_param_bound, V: RemEuclidU32> From<V> for $self {
            #[inline]
            fn from(from: V) -> Self {
                Self::new(from)
            }
        }

        #[allow(clippy::derive_hash_xor_eq)]
        impl<$generic_param: $generic_param_bound> Hash for $self {
            #[inline]
            fn hash<H: Hasher>(&self, state: &mut H) {
                Self::hash_impl(self, state)
            }
        }

        impl<$generic_param: $generic_param_bound> fmt::Display for $self {
            #[inline]
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                Self::display_impl(self, f)
            }
        }

        impl<$generic_param: $generic_param_bound> fmt::Debug for $self {
            #[inline]
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                Self::debug_impl(self, f)
            }
        }

        impl<$generic_param: $generic_param_bound> Neg for $self {
            type Output = $self;

            #[inline]
            fn neg(self) -> $self {
                Self::neg_impl(self)
            }
        }

        impl<$generic_param: $generic_param_bound> Neg for &'_ $self {
            type Output = $self;

            #[inline]
            fn neg(self) -> $self {
                <$self>::neg_impl(*self)
            }
        }

        impl_basic_traits!($($rest)*);
    };
}

    impl_basic_traits! {
        impl <M: Modulus> _ for StaticModInt<M> ;
        impl <I: Id     > _ for DynamicModInt<I>;
    }

    macro_rules! impl_bin_ops {
    () => {};
    (for<$($generic_param:ident : $generic_param_bound:tt),*> <$lhs_ty:ty> ~ <$rhs_ty:ty> -> $output:ty { { $lhs_body:expr } ~ { $rhs_body:expr } } $($rest:tt)*) => {
        impl <$($generic_param: $generic_param_bound),*> Add<$rhs_ty> for $lhs_ty {
            type Output = $output;

            #[inline]
            fn add(self, rhs: $rhs_ty) -> $output {
                <$output>::add_impl(apply($lhs_body, self), apply($rhs_body, rhs))
            }
        }

        impl <$($generic_param: $generic_param_bound),*> Sub<$rhs_ty> for $lhs_ty {
            type Output = $output;

            #[inline]
            fn sub(self, rhs: $rhs_ty) -> $output {
                <$output>::sub_impl(apply($lhs_body, self), apply($rhs_body, rhs))
            }
        }

        impl <$($generic_param: $generic_param_bound),*> Mul<$rhs_ty> for $lhs_ty {
            type Output = $output;

            #[inline]
            fn mul(self, rhs: $rhs_ty) -> $output {
                <$output>::mul_impl(apply($lhs_body, self), apply($rhs_body, rhs))
            }
        }

        impl <$($generic_param: $generic_param_bound),*> Div<$rhs_ty> for $lhs_ty {
            type Output = $output;

            #[inline]
            fn div(self, rhs: $rhs_ty) -> $output {
                <$output>::div_impl(apply($lhs_body, self), apply($rhs_body, rhs))
            }
        }

        impl_bin_ops!($($rest)*);
    };
}

    macro_rules! impl_assign_ops {
    () => {};
    (for<$($generic_param:ident : $generic_param_bound:tt),*> <$lhs_ty:ty> ~= <$rhs_ty:ty> { _ ~= { $rhs_body:expr } } $($rest:tt)*) => {
        impl <$($generic_param: $generic_param_bound),*> AddAssign<$rhs_ty> for $lhs_ty {
            #[inline]
            fn add_assign(&mut self, rhs: $rhs_ty) {
                *self = *self + apply($rhs_body, rhs);
            }
        }

        impl <$($generic_param: $generic_param_bound),*> SubAssign<$rhs_ty> for $lhs_ty {
            #[inline]
            fn sub_assign(&mut self, rhs: $rhs_ty) {
                *self = *self - apply($rhs_body, rhs);
            }
        }

        impl <$($generic_param: $generic_param_bound),*> MulAssign<$rhs_ty> for $lhs_ty {
            #[inline]
            fn mul_assign(&mut self, rhs: $rhs_ty) {
                *self = *self * apply($rhs_body, rhs);
            }
        }

        impl <$($generic_param: $generic_param_bound),*> DivAssign<$rhs_ty> for $lhs_ty {
            #[inline]
            fn div_assign(&mut self, rhs: $rhs_ty) {
                *self = *self / apply($rhs_body, rhs);
            }
        }

        impl_assign_ops!($($rest)*);
    };
}

    #[inline]
    fn apply<F: FnOnce(X) -> O, X, O>(f: F, x: X) -> O {
        f(x)
    }

    impl_bin_ops! {
        for<M: Modulus> <StaticModInt<M>     > ~ <StaticModInt<M>     > -> StaticModInt<M>  { { |x| x  } ~ { |x| x  } }
        for<M: Modulus> <StaticModInt<M>     > ~ <&'_ StaticModInt<M> > -> StaticModInt<M>  { { |x| x  } ~ { |&x| x } }
        for<M: Modulus> <&'_ StaticModInt<M> > ~ <StaticModInt<M>     > -> StaticModInt<M>  { { |&x| x } ~ { |x| x  } }
        for<M: Modulus> <&'_ StaticModInt<M> > ~ <&'_ StaticModInt<M> > -> StaticModInt<M>  { { |&x| x } ~ { |&x| x } }
        for<I: Id     > <DynamicModInt<I>    > ~ <DynamicModInt<I>    > -> DynamicModInt<I> { { |x| x  } ~ { |x| x  } }
        for<I: Id     > <DynamicModInt<I>    > ~ <&'_ DynamicModInt<I>> -> DynamicModInt<I> { { |x| x  } ~ { |&x| x } }
        for<I: Id     > <&'_ DynamicModInt<I>> ~ <DynamicModInt<I>    > -> DynamicModInt<I> { { |&x| x } ~ { |x| x  } }
        for<I: Id     > <&'_ DynamicModInt<I>> ~ <&'_ DynamicModInt<I>> -> DynamicModInt<I> { { |&x| x } ~ { |&x| x } }

        for<M: Modulus, T: RemEuclidU32> <StaticModInt<M>     > ~ <T> -> StaticModInt<M>  { { |x| x  } ~ { StaticModInt::<M>::new } }
        for<I: Id     , T: RemEuclidU32> <DynamicModInt<I>    > ~ <T> -> DynamicModInt<I> { { |x| x  } ~ { DynamicModInt::<I>::new } }
    }

    impl_assign_ops! {
        for<M: Modulus> <StaticModInt<M> > ~= <StaticModInt<M>     > { _ ~= { |x| x  } }
        for<M: Modulus> <StaticModInt<M> > ~= <&'_ StaticModInt<M> > { _ ~= { |&x| x } }
        for<I: Id     > <DynamicModInt<I>> ~= <DynamicModInt<I>    > { _ ~= { |x| x  } }
        for<I: Id     > <DynamicModInt<I>> ~= <&'_ DynamicModInt<I>> { _ ~= { |&x| x } }

        for<M: Modulus, T: RemEuclidU32> <StaticModInt<M> > ~= <T> { _ ~= { StaticModInt::<M>::new } }
        for<I: Id,      T: RemEuclidU32> <DynamicModInt<I>> ~= <T> { _ ~= { DynamicModInt::<I>::new } }
    }

    macro_rules! impl_folding {
    () => {};
    (impl<$generic_param:ident : $generic_param_bound:tt> $trait:ident<_> for $self:ty { fn $method:ident(_) -> _ { _($unit:expr, $op:expr) } } $($rest:tt)*) => {
        impl<$generic_param: $generic_param_bound> $trait<Self> for $self {
            #[inline]
            fn $method<S>(iter: S) -> Self
            where
                S: Iterator<Item = Self>,
            {
                iter.fold($unit, $op)
            }
        }

        impl<'a, $generic_param: $generic_param_bound> $trait<&'a Self> for $self {
            #[inline]
            fn $method<S>(iter: S) -> Self
            where
                S: Iterator<Item = &'a Self>,
            {
                iter.fold($unit, $op)
            }
        }

        impl_folding!($($rest)*);
    };
}

    impl_folding! {
        impl<M: Modulus> Sum<_>     for StaticModInt<M>  { fn sum(_)     -> _ { _(Self::raw(0), Add::add) } }
        impl<M: Modulus> Product<_> for StaticModInt<M>  { fn product(_) -> _ { _(Self::raw(1), Mul::mul) } }
        impl<I: Id     > Sum<_>     for DynamicModInt<I> { fn sum(_)     -> _ { _(Self::raw(0), Add::add) } }
        impl<I: Id     > Product<_> for DynamicModInt<I> { fn product(_) -> _ { _(Self::raw(1), Mul::mul) } }
    }
}
use modint::*;

#![allow(dead_code, unused_imports)]
#[rustfmt::skip] mod writer {use std::fmt::Display;use std::io::{stdout, BufWriter, Error as IoError, Stdout, Write};#[derive(Debug)] pub struct Writer<W: Write> { writer: BufWriter<W>, }  #[derive(Debug, Clone)] pub struct Format<'a> {  separator: &'a str,  ending: &'a str, }  impl<'a> Format<'a> { pub fn separator(self, separator: &'a str) -> Self { Self { separator, ..self } }  pub fn ending(self, ending: &'a str) -> Self { Self { ending, ..self } } }  impl Default for Format<'_> { fn default() -> Self { Format { separator: " ", ending: "\n", } } }  impl Writer<Stdout> { pub fn stdout() -> Self { Self::new(stdout()) } }  impl<W: Write> Writer<W> { pub fn new(writer: W) -> Self { Self { writer: BufWriter::new(writer), } }  pub fn write<M, T: Writable<M>>(&mut self, val: T) -> Result<(), IoError> { self.write_with(val, &Format::default()) }  pub fn write_with<M, T: Writable<M>>(&mut self, val: T, fmt: &Format) -> Result<(), IoError> { val.write_to(&mut self.writer, fmt) }  pub fn flush(&mut self) -> Result<(), IoError> { self.writer.flush() } }  pub trait Writable<Mode> { fn write_to<W: Write>(self, w: &mut W, fmt: &Format) -> Result<(), IoError>;}  #[non_exhaustive] pub struct Single;impl<T: Display> Writable<Single> for T { fn write_to<W: Write>(self, w: &mut W, fmt: &Format) -> Result<(), IoError> { write!(w, "{}{}", self, fmt.ending) } }  #[non_exhaustive] pub struct Many;impl<I> Writable<Many> for I where I: Iterator, I::Item: Display, { fn write_to<W: Write>(mut self, w: &mut W, fmt: &Format) -> Result<(), IoError> { if let Some(x) = self.next() { write!(w, "{}", x)?;} else {  return Ok(());}  for x in self { write!(w, "{}{}", fmt.separator, x)?;} write!(w, "{}", fmt.ending) } }  #[non_exhaustive] pub struct Slice;impl<T: Display> Writable<Slice> for &[T] { fn write_to<W: Write>(self, w: &mut W, fmt: &Format) -> Result<(), IoError> { self.iter().write_to(w, fmt) } }  #[macro_export]   macro_rules! out { ($writer:expr, $val:expr) => { $writer.write($val).expect("failed to write token");};($writer:expr, $val:expr, $($builder_name:ident = $value:expr),+) => { let mut fmt = Format::default();$( fmt = fmt.$builder_name($value);)+ $writer.write_with($val, &fmt).expect("failed to write token");};} }
#[rustfmt::skip] mod scanner {use std::fmt::Debug;use std::io::{stdin, BufReader, Bytes, Error as IoError, Read, Stdin};use std::str::{self, FromStr, Utf8Error};#[derive(Debug)] pub struct Scanner<R: Read> { bytes: Bytes<BufReader<R>>, buf: Vec<u8>, }      pub trait Instructions { type Target;type Error;fn read_from<R: Read>(scanner: &mut Scanner<R>) -> Result<Self::Target, Self::Error>;}  impl<T: FromStr> Instructions for T { type Target = T;type Error = ScanError<T>;fn read_from<R: Read>(scanner: &mut Scanner<R>) -> Result<Self::Target, Self::Error> { scanner.read_token() } }  #[derive(Debug)] pub enum ScanError<T: FromStr> { Io(IoError), Parse(T::Err, String), NonUtf8(Utf8Error, Vec<u8>), }  impl Scanner<Stdin> { pub fn stdin() -> Self { Self::new(stdin()) } }  impl<R: Read> Scanner<R> { pub fn new(reader: R) -> Self { Self { bytes: BufReader::new(reader).bytes(), buf: Vec::new(), } }  pub fn read_token<T: FromStr>(&mut self) -> Result<T, ScanError<T>> { debug_assert!(self.buf.is_empty());for b in &mut self.bytes { let b = b.map_err(ScanError::Io)?;if b.is_ascii_whitespace() {  if self.buf.is_empty() { continue;} else { break;} } else { self.buf.push(b);} }   match str::from_utf8(&self.buf) { Err(err) => Err(ScanError::NonUtf8(err, std::mem::take(&mut self.buf))), Ok(s) => { let ret = s.parse().map_err(|err| ScanError::Parse(err, s.to_owned()));self.buf.clear();ret } } }  pub fn read<T: Instructions>(&mut self) -> Result<T::Target, T::Error> { T::read_from(self) } }  #[macro_use] pub mod macros { use super::*;use std::fmt::{self, Debug};use std::io::Read;use std::marker::PhantomData;use std::num::NonZeroUsize;use std::str::FromStr;pub struct UsizeM1(());impl Instructions for UsizeM1 { type Target = usize;type Error = ScanError<NonZeroUsize>;fn read_from<R: Read>(scanner: &mut Scanner<R>) -> Result<Self::Target, Self::Error> { Ok(scanner.read_token::<NonZeroUsize>()?.get() - 1) } }   pub struct LenArray<T>(PhantomData<T>);impl<T: FromStr> Instructions for LenArray<T> { type Target = Vec<T>;type Error = LenArrayScanError<T>;fn read_from<R: Read>(scanner: &mut Scanner<R>) -> Result<Self::Target, Self::Error> { let len = scanner .read_token::<usize>() .map_err(LenArrayScanError::Len)?;let mut arr = Vec::with_capacity(len);for i in 0..len { let elem = scanner .read_token::<T>() .map_err(|e| LenArrayScanError::Data(i, e))?;arr.push(elem);} Ok(arr) } }  pub enum LenArrayScanError<T: FromStr> { Len(ScanError<usize>), Data(usize, ScanError<T>), }  impl<T> Debug for LenArrayScanError<T> where T: Debug + FromStr, T::Err: Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use self::LenArrayScanError::*;match self { Len(e) => f.debug_tuple("Len").field(e).finish(), Data(i, e) => f.debug_tuple("Data").field(i).field(e).finish(), } } }  #[macro_export] macro_rules! scan { (@scan 1 $scan:expr, $type:ty) => { $scan .read::<$type>() .expect(concat!("failed to read token of type ", stringify!($type))) };(@scan 2 $scan:expr, $type:ty, $n:expr) => { (0..$n) .map(|_| scan!(@scan 1 $scan, $type)) .collect::<Vec<_>>() };(@accum ($scan:expr) () -> ($($body:tt)*)) => { ($($body)*) };(@accum ($scan:expr) ($type:ty) -> ($($body:tt)*)) => { scan!(@accum ($scan) () -> ($($body)* scan!(@scan 1 $scan, $type))) };(@accum ($scan:expr) ($type:ty, $($next:tt)*) -> ($($body:tt)*)) => { scan!(@accum ($scan) ($($next)*) -> ($($body)* scan!(@scan 1 $scan, $type),)) };(@accum ($scan:expr) ($n:tt * $type:ty) -> ($($body:tt)*)) => { scan!(@accum ($scan) () -> ($($body)* scan!(@scan 2 $scan, $type, $n))) };(@accum ($scan:expr) ($n:tt * $type:ty, $($next:tt)*) -> ($($body:tt)*)) => { scan!(@accum ($scan) ($($next)*) -> ($($body)* scan!(@scan 2 $scan, $type, $n),)) };($scan:expr, $($arg:tt)+) => { scan!(@accum ($scan) ($($arg)+) -> ()) };} } }
#[rustfmt::skip] mod util {   use std::cmp::Reverse; pub trait IntoVec<T, _Hack> { fn into_vec(self) -> Vec<T>;}  #[non_exhaustive] pub struct Owned;impl<I, T> IntoVec<T, Owned> for I where I: Iterator<Item = T>, { fn into_vec(self) -> Vec<T> { self.collect() } }  #[non_exhaustive] pub struct Reference;impl<'a, I, T> IntoVec<T, Reference> for I where I: Iterator<Item = &'a T>, T: Clone + 'a, { fn into_vec(self) -> Vec<T> { self.cloned().collect() } }  pub trait Argmax { fn argmax(self) -> Option<usize>;fn argmin(self) -> Option<usize>;}  impl<I> Argmax for I where I: Iterator, I::Item: Ord, { fn argmax(self) -> Option<usize> { self.fold((0, None), |(i, mx), next| { if let Some((mx_i, mx_v)) = mx { if next.gt(&mx_v) { (i + 1, Some((i, next))) } else { (i + 1, Some((mx_i, mx_v))) } } else { (i + 1, Some((i, next))) } }) .1 .map(|x| x.0) }  fn argmin(self) -> Option<usize> { self.map(Reverse).argmax() } }  pub trait Sorted<T> { fn sorted(self) -> Self;}  impl<T> Sorted<T> for Vec<T> where T: Ord, { fn sorted(mut self) -> Self { self.sort();self } }  pub trait SortedBy<T> { fn sorted_by<F, K>(self, f: F) -> Self where F: FnMut(&T) -> K, K: Ord;}  impl<T> SortedBy<T> for Vec<T> { fn sorted_by<F, K>(mut self, f: F) -> Self where F: FnMut(&T) -> K, K: Ord, { self.sort_by_key(f);self } }  pub trait Choose { fn choose<T>(self, a: T, b: T) -> T;fn choose_by<T>(self, a: impl FnOnce() -> T, b: impl FnOnce() -> T) -> T;}  impl Choose for bool { fn choose<T>(self, a: T, b: T) -> T { if self { a } else { b } }  fn choose_by<T>(self, a: impl FnOnce() -> T, b: impl FnOnce() -> T) -> T { if self { a() } else { b() } } }  #[macro_export] macro_rules! p { ( $( $x:expr ),* ) => { #[cfg(any(debug_assertions, debug_print))] { dbg!( $( & $x, )* );} };}  pub fn fix<A, R>(f: &dyn Fn(&dyn Fn(A) -> R, A) -> R) -> impl Fn(A) -> R + '_ { move |arg| f(&fix(&f), arg) }  pub trait Assign<T> { fn assign(&mut self, val: T);}  impl<T> Assign<T> for Option<T> {  fn assign(&mut self, val: T) { assert!(self.is_none(), ".assign() called on Some variant");*self = Some(val);} } }
#[rustfmt::skip] mod prefix_sum {use std::{ fmt::{self, Debug, Formatter}, marker::PhantomData, ops::{Add, Bound, Range, RangeBounds, Sub}, };#[derive(Clone)] pub struct PrefixOp<T, F, I> { fwd: F, inv: Option<I>, marker: PhantomData<fn(&T, &T) -> T>, }  impl<T, F> PrefixOp<T, F, ()> where F: Fn(&T, &T) -> T, {  pub fn new(op: F) -> Self { PrefixOp { fwd: op, inv: None, marker: PhantomData, } } }  impl<T, F, I> PrefixOp<T, F, I> where F: Fn(&T, &T) -> T, I: Fn(&T, &T) -> T, {     pub fn new_invertible(op: F, inverse: I) -> Self { PrefixOp { fwd: op, inv: Some(inverse), marker: PhantomData, } } }  impl<T, F, I> PrefixOp<T, F, I> where F: Fn(&T, &T) -> T, I: Clone, {  pub fn build(&self, mut arr: Vec<T>) -> PrefixArray<T, F, I> { for i in 1..arr.len() { arr[i] = (self.fwd)(&arr[i - 1], &arr[i]);} PrefixArray { pref: arr, fwd: PhantomData, inv: self.inv.clone(), } } }        #[derive(Clone)] pub struct PrefixArray<T, F, I> { pref: Vec<T>,   fwd: PhantomData<F>, inv: Option<I>, }  impl<T, F, I> PrefixArray<T, F, I> {  pub fn len(&self) -> usize { self.pref.len() }   pub fn is_empty(&self) -> bool { self.pref.is_empty() }   #[track_caller] fn verify_range_bounds(&self, range: impl RangeBounds<usize>) -> Range<usize> { let start = match range.start_bound() { Bound::Unbounded => 0, Bound::Included(&x) => x, Bound::Excluded(&x) => x + 1, };let end = match range.end_bound() { Bound::Unbounded => self.len(), Bound::Included(&x) => x + 1, Bound::Excluded(&x) => x, };assert!( start < end, "range inverted: start >= end ({} >= {})", start, end );assert!( end <= self.len(), "range out of bounds: end > len ({} > {})", end, self.len() );Range { start, end } }     #[track_caller] pub fn query_prefix(&self, range: impl RangeBounds<usize>) -> T where T: Clone, { let Range { start, end } = self.verify_range_bounds(range);assert!(start == 0, "query start bound is non-zero: {} > 0", start);self.pref[end - 1].clone() } }  impl<T, F, I> PrefixArray<T, F, I> where I: Fn(&T, &T) -> T, {  #[track_caller] pub fn query(&self, range: impl RangeBounds<usize>) -> T where T: Clone, { let Range { start, end } = self.verify_range_bounds(range);if start == 0 { self.pref[end - 1].clone() } else { (self .inv .as_ref() .expect("range query is not supported on non-invertible operation"))( &self.pref[end - 1], &self.pref[start - 1], ) } } }  impl<T, F, I> Debug for PrefixOp<T, F, I> where T: Debug, { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("PrefixOp").finish_non_exhaustive() } }  impl<T, F, I> Debug for PrefixArray<T, F, I> where T: Debug, { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("PrefixArray") .field("pref", &self.pref) .finish_non_exhaustive() } }  type NextFn<T> = fn(&T, &T) -> T;pub struct PrefixSum<T>(PhantomData<T>);impl<T> PrefixSum<T> where T: Add<Output = T> + Sub<Output = T> + Clone, {  pub fn op() -> PrefixOp<T, NextFn<T>, NextFn<T>> { PrefixOp::new_invertible(|a, b| a.clone() + b.clone(), |b, a| b.clone() - a.clone()) }   pub fn build(arr: Vec<T>) -> PrefixArray<T, NextFn<T>, NextFn<T>> { Self::op().build(arr) } } }
#[rustfmt::skip] mod combinatorics {use crate::{num::Integer, number_theory::mod_mulinv};pub fn next_permutation<T>(perm: &mut [T]) -> bool where T: Ord, { if perm.is_empty() { return false;}   let i = match Iterator::zip(perm.iter(), perm[1..].iter()).rposition(|(x, y)| x < y) { None => {  perm.reverse();return false;} Some(x) => x, };let j = perm .iter() .rposition(|x| &perm[i] < x) .expect("inconsistent Ord implementation");perm.swap(i, j);perm[i + 1..].reverse();true }       #[derive(Debug, Clone)]  pub struct Factorials<N> { m: N, fact: Vec<N>, fact_inv: Vec<N>, }  impl<N> Factorials<N> where N: Integer + Clone, { #[inline] fn as_n(x: usize) -> N { N::from_usize(x).expect("inconsistent Integer implementation") } #[inline] fn as_usize(x: &N) -> usize { N::as_usize(x).expect("inconsistent Integer implementation") }      #[track_caller] pub fn new(n: N, m: N) -> Self { let cap = n .as_usize() .and_then(|x| x.checked_add(1)) .expect("required capacity overflowed usize");assert!(cap > 0, "n must be non-negative");let mut fact = Vec::with_capacity(cap);fact.push(N::one());let mut cur = N::one();for i in 1..cap { cur = (cur * Self::as_n(i)).imod(&m);fact.push(cur.clone());}   let mut fact_inv = Vec::with_capacity(cap);let mut cur = mod_mulinv(fact[cap - 1].clone(), m.clone());for i in (0..cap).rev() { fact_inv.push(cur.clone());cur = (cur * Self::as_n(i)).imod(&m);} fact_inv.reverse();debug_assert_eq!(fact.len(), cap);debug_assert_eq!(fact_inv.len(), cap);Factorials { m, fact, fact_inv } }   pub fn len(&self) -> usize { self.fact.len() }    pub fn is_empty(&self) -> bool { false }   pub fn n(&self) -> N { Self::as_n(self.fact.len() - 1) }   #[track_caller] fn verify_n<'a>(&self, n: &'a N) -> &'a N { assert!( N::zero() <= *n && *n <= self.n(), "n is outside precomputed range" );n }     #[track_caller] pub fn factorial(&self, n: &N) -> N { let n = self.verify_n(n);self.fact[Self::as_usize(n)].clone() }     #[track_caller] pub fn factorial_inverse(&self, n: &N) -> N { let n = self.verify_n(n);self.fact_inv[Self::as_usize(n)].clone() }     #[track_caller] pub fn choose(&self, n: N, k: N) -> N { self.verify_n(&n);assert!(k >= N::zero(), "k is negative");if k <= n {  ((self.fact[Self::as_usize(&n)].clone() * self.fact_inv[Self::as_usize(&k)].clone()) .imod(&self.m) * self.fact_inv[Self::as_usize(&(n - k))].clone()) .imod(&self.m) } else { N::zero() } } } }
#[rustfmt::skip] mod number_theory {use crate::num::Integer;use std::mem;pub fn gcd<N: Integer>(mut a: N, mut b: N) -> N { while b != N::zero() { mem::swap(&mut a, &mut b);b = b.imod(&a);} a.iabs() }      #[allow(clippy::many_single_char_names)] pub fn egcd<N: Integer + Clone>(a: N, b: N) -> (N, N, N) { if b == N::zero() { ( a.iabs(), if a >= N::zero() { N::one() } else { N::zero() - N::one() }, N::zero(), ) } else { let (g, s, t) = egcd(b.clone(), a.imod(&b));(g, t.clone(), s - a.idiv(&b) * t) } }       #[track_caller] pub fn mod_exp<N: Integer + Clone>(a: N, mut b: N, m: N) -> N { let zero = N::zero();let one = N::one();let two = N::one() + N::one();assert!(m > zero, "modulus must be positive");if b < zero { return mod_exp(mod_mulinv(a, m.clone()), zero - b, m);}  let mut x = N::one();let mut pwr = a;while b > N::zero() { if b.imod(&two) == one { x = (x * pwr.clone()).imod(&m);} pwr = (pwr.clone() * pwr).imod(&m);b = b.idiv(&two);} x }      #[track_caller] pub fn mod_mulinv<N: Integer + Clone>(a: N, m: N) -> N { let zero = N::zero();let one = N::one();assert!(m > zero, "modulus must be positive");let (g, s, _) = egcd(a, m.clone());assert!(g == one, "multiplicative inverse does not exist");s.imod(&m) }         #[derive(Debug, Clone)]   pub struct PrimeSieve<N> { lowest_factor: Vec<N>, primes: Vec<N>, }  impl<N> PrimeSieve<N> where N: Integer + Clone, { #[inline] fn as_n(x: usize) -> N { N::from_usize(x).expect("inconsistent Integer implementation") } #[inline] fn as_usize(x: &N) -> usize { N::as_usize(x).expect("inconsistent Integer implementation") }     #[track_caller] pub fn new(n: N) -> Self { let cap = n .as_usize() .and_then(|x| x.checked_add(1)) .expect("capacity overflowed usize");assert!(cap > 0, "n must be non-negative");let mut lowest_factor = vec![N::zero(); cap];let mut primes = vec![];for i in 2..cap { if lowest_factor[i] == N::zero() { lowest_factor[i] = Self::as_n(i);primes.push(Self::as_n(i));}    let lowest_factor_i = lowest_factor[i].clone();for (p, p_usize) in primes .iter() .map(|p| (p, Self::as_usize(p))) .take_while(|(p, p_usize)| i * p_usize < cap && p <= &&lowest_factor_i) { lowest_factor[i * p_usize] = p.clone();} }  PrimeSieve { lowest_factor, primes, } }   pub fn len(&self) -> usize { self.lowest_factor.len() }    pub fn is_empty(&self) -> bool { false }   pub fn n(&self) -> N { Self::as_n(self.lowest_factor.len() - 1) }      #[track_caller] pub fn is_prime(&self, x: &N) -> bool { assert!(*x >= N::zero(), "x must be non-negative");let n = self.n();if *x <= n { *x > N::zero() && self.lowest_factor[Self::as_usize(x)] == *x } else if *x <= n.clone() * n { for p in self.primes.iter() { if x.imod(p) == N::zero() { return false;} } true } else { panic!("unable to determine primality: x > n^2");} }       #[track_caller] pub fn lowest_factor(&self, x: &N) -> N { assert!(*x >= N::zero(), "x must be non-negative");let n = self.n();if *x <= n { self.lowest_factor[Self::as_usize(x)].clone() } else if *x <= n.clone() * n { for p in self .primes .iter() .take_while(|&p| p.clone() * p.clone() <= *x) { if x.imod(p) == N::zero() { return p.clone();} } x.clone() } else { panic!("unable to determine lowest factor: x > n^2",) } }      #[track_caller] pub fn factorize(&self, mut x: N) -> Vec<N> { let n = self.n();assert!(x > N::zero(), "cannot factorize non-positive numbers");assert!(x <= n.clone() * n.clone(), "unable to factorize: x > n^2",);let mut factors = Vec::new();let x2 = x.clone();let mut primes = self .primes .iter() .take_while(|&p| p.clone() * p.clone() <= x2);while x > N::one() { if x <= n { let f = &self.lowest_factor[Self::as_usize(&x)];factors.push(f.clone());x = x.idiv(f);} else if let Some(p) = primes.next() { while x.imod(p) == N::zero() { factors.push(p.clone());x = x.idiv(p);} } else {  factors.push(x);break;} } factors } } }
#[rustfmt::skip] mod num {use std::convert::{TryFrom, TryInto};use std::ops::{Add, Div, Mul, Rem, Sub};pub trait Num: Ord + Add<Output = Self> + Sub<Output = Self> + Mul<Output = Self> + Div<Output = Self> + Rem<Output = Self> + FromPrimitive + IntoPrimitive + Sized {  fn zero() -> Self;fn one() -> Self;}  pub trait FromPrimitive: Sized {  fn from_u64(x: u64) -> Option<Self>;fn from_i64(x: i64) -> Option<Self>;fn from_usize(x: usize) -> Option<Self> { Self::from_u64(x as u64) }  fn from_isize(x: isize) -> Option<Self> { Self::from_i64(x as i64) } }  pub trait IntoPrimitive {  fn as_u64(&self) -> Option<u64>;fn as_i64(&self) -> Option<i64>;fn as_usize(&self) -> Option<usize> { self.as_u64().and_then(|x| x.try_into().ok()) }  fn as_isize(&self) -> Option<isize> { self.as_i64().and_then(|x| x.try_into().ok()) } }       pub trait Integer: Num {  fn idiv(&self, x: &Self) -> Self;fn imod(&self, x: &Self) -> Self;fn iabs(&self) -> Self;}  macro_rules! generate_integer_impl_for_primitive { ($( ($ty:ty, $unsigned:tt) ),+) => { $( impl FromPrimitive for $ty { #[inline(always)] fn from_u64(x: u64) -> Option<Self> { <$ty>::try_from(x).ok() } #[inline(always)] fn from_i64(x: i64) -> Option<Self> { <$ty>::try_from(x).ok() } }  impl IntoPrimitive for $ty { #[inline(always)] fn as_u64(&self) -> Option<u64> { u64::try_from(*self).ok() } #[inline(always)] fn as_i64(&self) -> Option<i64> { i64::try_from(*self).ok() } }  impl Num for $ty { #[inline(always)] fn zero() -> Self { 0 } #[inline(always)] fn one() -> Self { 1 } }  impl Integer for $ty { #[inline(always)] fn idiv(&self, x: &Self) -> Self { self.div_euclid(*x) } #[inline(always)] fn imod(&self, x: &Self) -> Self { self.rem_euclid(*x) } generate_iabs_impl!($unsigned);} )+ };}  macro_rules! generate_iabs_impl { (true) => { #[inline(always)] fn iabs(&self) -> Self { *self } };(false) => { #[inline(always)] fn iabs(&self) -> Self { self.abs() } };}  generate_integer_impl_for_primitive!( (u8, true), (u16, true), (u32, true), (u64, true), (u128, true), (usize, true), (i8, false), (i16, false), (i32, false), (i64, false), (i128, false), (isize, false) );}

use combinatorics::{next_permutation, Factorials};
use number_theory::{egcd, gcd, mod_exp, mod_mulinv, PrimeSieve};
use prefix_sum::{PrefixOp, PrefixSum};
use scanner::{
    macros::{LenArray, UsizeM1},
    Scanner,
};
use util::{fix, Argmax, Assign, Choose, IntoVec, Sorted};
use writer::{Format, Writer};

fn main() {
    let mut sc = Scanner::stdin();
    let mut wr = Writer::stdout();

    let (n, k) = scan!(sc, i64, i64);
    const MOD: i64 = 1_000_000_007;
    let fact = Factorials::new(n, MOD);
    let mut ans = 0;
    for i in 0..=i64::min(n, k) {
        ans = (ans + fact.choose(n, i)) % MOD;
    }
    out!(wr, ans);
}

#[allow(unused_imports)]
use std::{
    cmp,
    collections::{BinaryHeap, HashMap, HashSet, VecDeque},
    hash::Hash,
    io::{self, BufWriter, Read, StdoutLock, Write},
    str::Lines,
};

const MODVAL: u64 = 1e9 as u64 + 7;

#[allow(unused_mut, unused_variables)]
fn main() -> io::Result<()> {
    let mut input = String::new();
    io::stdin().lock().read_to_string(&mut input).unwrap();
    let mut input = input.lines();

    let out = io::stdout();
    let mut out = BufWriter::new(out.lock());

    let line = next_line_as_u64_vec(&mut input);
    let n = line[0];
    let k = line[1];

    let mut m = 1;
    let fact = FactorialsMod::new(n as usize, MODVAL);
    for k in 1..=cmp::min(n, k) {
        m += bi_coefficient_mod(n, k, &fact, MODVAL);
    }
    writeln!(out, "{}", m % MODVAL)?;

    Ok(())
}

#[allow(dead_code)]
fn bi_coefficient_mod(n: u64, k: u64, fact: &FactorialsMod, modval: u64) -> u64 {
    if n == k {
        return 1;
    }
    let mut res = fact.get(n as usize).unwrap();
    res *= mod_inverse(fact.get(k as usize).unwrap(), modval);
    res %= modval;
    res *= mod_inverse(fact.get((n - k) as usize).unwrap(), modval);
    res %= modval;
    res
}

#[allow(dead_code)]
fn pow_mod(a: u64, b: u64, modval: u64) -> u64 {
    let mut a = a % modval;
    if a == 0 {
        return 0;
    }
    let mut b = b;
    let mut res = 1u64;
    while b > 0 {
        if b & 1 != 0 {
            res *= a;
            res %= modval;
            b -= 1;
        }
        a *= a;
        a %= modval;
        b >>= 1;
    }
    res
}

#[allow(dead_code)]
fn mod_inverse(a: u64, modval: u64) -> u64 {
    pow_mod(a, modval - 2, modval)
}

#[derive(Debug, Clone)]
struct FactorialsMod {
    numbers: Vec<u64>,
}

#[allow(dead_code)]
impl FactorialsMod {
    fn new(n: usize, modval: u64) -> Self {
        let mut numbers = vec![0; n + 1];
        let mut fac = 1u64;
        for i in 1..=n {
            fac *= i as u64;
            fac %= modval;
            numbers[i] = fac;
        }
        FactorialsMod { numbers }
    }

    fn get(&self, n: usize) -> Option<u64> {
        self.numbers.get(n).map(|&x| x)
    }
}

#[allow(dead_code)]
fn next_line(input: &mut Lines) -> String {
    input.next().unwrap().to_string()
}

#[allow(dead_code)]
fn next_line_as_u64(input: &mut Lines) -> u64 {
    let s = input.next().unwrap();
    let n: u64 = s.parse().unwrap();
    n
}

#[allow(dead_code)]
fn next_line_as_i64(input: &mut Lines) -> i64 {
    let s = input.next().unwrap();
    let n: i64 = s.parse().unwrap();
    n
}

#[allow(dead_code)]
fn next_line_as_string_vec(input: &mut Lines) -> Vec<String> {
    let s = input.next().unwrap();
    let a = s.split(" ").collect::<Vec<&str>>();
    a.iter().map(|&s| s.to_string()).collect()
}

#[allow(dead_code)]
fn next_line_as_char_vec(input: &mut Lines) -> Vec<char> {
    let s = input.next().unwrap();
    let a: Vec<char> = s.chars().collect();
    a
}

#[allow(dead_code)]
fn next_line_as_u64_vec(input: &mut Lines) -> Vec<u64> {
    let s = input.next().unwrap();
    let a: Vec<u64> = s.split(" ").map(|s| s.parse().unwrap()).collect();
    a
}

#[allow(dead_code)]
fn next_line_as_i64_vec(input: &mut Lines) -> Vec<i64> {
    let s = input.next().unwrap();
    let a: Vec<i64> = s.split(" ").map(|s| s.parse().unwrap()).collect();
    a
}

#[allow(dead_code)]
fn write_bool_answer(answer: bool, out: &mut BufWriter<StdoutLock>) {
    if answer {
        writeln!(out, "yes").unwrap();
    } else {
        writeln!(out, "no").unwrap();
    }
}

#![allow(dead_code, unused_macros, unused_imports)]
use std::cell::RefCell;
use std::cmp::Ordering;
use std::collections::*;
use std::error::Error;
use std::fmt::write;
use std::hash::Hash;
use std::io;
use std::io::prelude::*;
use std::io::StdinLock;
use std::io::StdoutLock;
use std::io::Write;
use std::io::{stdin, stdout, BufRead, BufWriter};
use std::ops::Add;
use std::thread::panicking;

macro_rules! fprintvec {
    ($dst:expr, $arg:expr) => {{
        writeln!(
            $dst,
            "{}",
            $arg.iter()
                .map(|x| format!("{} ", x))
                .collect::<Vec<String>>()
                .join("")
        )
        .ok();
    }};
}

pub struct Scanner<B> {
    reader: B,
    buf_str: Vec<u8>,
    buf_iter: std::str::SplitWhitespace<'static>,
}
impl<B: BufRead> Scanner<B> {
    pub fn new(reader: B) -> Self {
        Self {
            reader,
            buf_str: Vec::new(),
            buf_iter: "".split_whitespace(),
        }
    }
    pub fn next<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buf_iter.next() {
                return token.parse().ok().expect("Failed parse");
            }
            self.buf_str.clear();
            self.reader
                .read_until(b'\n', &mut self.buf_str)
                .expect("Failed read");
            self.buf_iter = unsafe {
                let slice = std::str::from_utf8_unchecked(&self.buf_str);
                std::mem::transmute(slice.split_whitespace())
            }
        }
    }

    pub fn next_split<T: std::str::FromStr>(&mut self) -> Vec<T> {
        loop {
            let mut v = Vec::new();
            while let Some(token) = self.buf_iter.next() {
                v.push(token.parse().ok().expect("Failed parse"));
            }
            if v.len() > 0 {
                return v;
            }

            self.buf_str.clear();
            self.reader
                .read_until(b'\n', &mut self.buf_str)
                .expect("Failed read");
            self.buf_iter = unsafe {
                let slice = std::str::from_utf8_unchecked(&self.buf_str);
                std::mem::transmute(slice.split_whitespace())
            }
        }
    }
}

fn lcm(first: usize, second: usize) -> usize {
    first * second / gcd(first, second)
}

fn gcd(first: usize, second: usize) -> usize {
    let mut max = first;
    let mut min = second;
    if min > max {
        let val = max;
        max = min;
        min = val;
    }

    loop {
        let res = max % min;
        if res == 0 {
            return min;
        }

        max = min;
        min = res;
    }
}

//let fmc = ModMath::<MOD_VAL>::new(CACHE_SIZE);
//let fmc = ModMath::<1000000007>::new(100005);

#[derive(Clone, Default, Debug)]
struct ModMath<const MODVAL: i64> {
    fact: Vec<i64>,
    inv: Vec<i64>,
    fact_cache_size: i64,
}

impl<const MODVAL: i64> ModMath<MODVAL> {
    fn new(fact_cache_size: usize) -> ModMath<MODVAL> {
        let mut fmc = ModMath {
            ..Default::default()
        };
        fmc.fact.resize(fact_cache_size, 0);
        fmc.inv.resize(fact_cache_size, 0);
        fmc.fact[0] = 1;
        fmc.inv[0] = 1;
        fmc.fact_cache_size = fact_cache_size as i64; //set this after so the calculation doesn't return cached value
        for i in 1..fact_cache_size {
            fmc.fact[i] = fmc.mult_mod(fmc.fact[i - 1], i as i64);
            fmc.inv[i] = fmc.inv_mod(fmc.fact[i]);
        }
        fmc
    }

    fn factorial_mod(&self, n: i64) -> i64 {
        if n < self.fact_cache_size {
            return self.fact[n as usize];
        }
        let mut t = self.fact[self.fact_cache_size as usize - 1];
        for x in self.fact_cache_size..=n {
            t = (t * x) % MODVAL;
        }
        t
    }

    fn permutations_mod(&self, n: i64, r: i64) -> i64 {
        let a = self.factorial_mod(n);
        let b = self.inv_fact_mod(n - r);
        return self.mult_mod(a, b);
    }

    fn inv_fact_mod(&self, n: i64) -> i64 {
        if n < self.fact_cache_size {
            return self.inv[n as usize];
        }
        self.pow_mod(self.factorial_mod(n), MODVAL - 2)
    }

    fn inv_mod(&self, n: i64) -> i64 {
        self.pow_mod(n, MODVAL - 2)
    }

    fn combinations_mod(&self, n: i64, r: i64) -> i64 {
        let a = self.factorial_mod(n);
        let b = self.inv_fact_mod(r);
        let c = self.inv_fact_mod(n - r);
        return self.mult_mod(self.mult_mod(a, b), c);
    }

    fn pow_mod(&self, mut base: i64, mut pow: i64) -> i64 {
        if pow == 0 {
            return 1;
        }
        let mut result = 1;
        while pow > 0 {
            if pow & 1 == 1 {
                result = (result * base) % MODVAL;
            }
            pow /= 2;
            base = (base * base) % MODVAL;
        }
        result
    }

    fn mult_mod(&self, a: i64, b: i64) -> i64 {
        let a = a as i128;
        let b = b as i128;
        ((a * b) % MODVAL as i128) as i64
    }

    fn add_mod(&self, a: i64, b: i64) -> i64 {
        ((a % MODVAL) + (b % MODVAL)) % MODVAL
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let stdout = io::stdout();
    let lock = stdout.lock();
    let stdin = io::stdin();
    let mut ow = io::BufWriter::new(lock);
    let mut scan = Scanner::new(stdin.lock());

    // let n_tests = scan.next::<i64>();
    let n_tests = 1;
    let fmc = ModMath::<1000000007>::new(100005);
    for t_num in 1..=n_tests {
        let n = scan.next::<usize>();
        let k = scan.next::<usize>();

        let mut start = 1;

        for i in 1..=(std::cmp::min(n, k)) {
            start = fmc.add_mod(start, fmc.combinations_mod(n as i64, i as i64));
        }

        writeln!(ow, "{}", start);
    }
    Ok(())
}

#![allow(dead_code, unused_macros, unused_imports)]
use std::cell::RefCell;
use std::cmp::Ordering;
use std::collections::*;
use std::error::Error;
use std::fmt::write;
use std::hash::Hash;
use std::io;
use std::io::prelude::*;
use std::io::StdinLock;
use std::io::StdoutLock;
use std::io::Write;
use std::io::{stdin, stdout, BufRead, BufWriter};
use std::ops::Add;
use std::thread::panicking;

macro_rules! fprintvec {
    ($dst:expr, $arg:expr) => {{
        writeln!(
            $dst,
            "{}",
            $arg.iter()
                .map(|x| format!("{} ", x))
                .collect::<Vec<String>>()
                .join("")
        )
        .ok();
    }};
}

pub struct Scanner<B> {
    reader: B,
    buf_str: Vec<u8>,
    buf_iter: std::str::SplitWhitespace<'static>,
}
impl<B: BufRead> Scanner<B> {
    pub fn new(reader: B) -> Self {
        Self {
            reader,
            buf_str: Vec::new(),
            buf_iter: "".split_whitespace(),
        }
    }
    pub fn next<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buf_iter.next() {
                return token.parse().ok().expect("Failed parse");
            }
            self.buf_str.clear();
            self.reader
                .read_until(b'\n', &mut self.buf_str)
                .expect("Failed read");
            self.buf_iter = unsafe {
                let slice = std::str::from_utf8_unchecked(&self.buf_str);
                std::mem::transmute(slice.split_whitespace())
            }
        }
    }

    pub fn next_split<T: std::str::FromStr>(&mut self) -> Vec<T> {
        loop {
            let mut v = Vec::new();
            while let Some(token) = self.buf_iter.next() {
                v.push(token.parse().ok().expect("Failed parse"));
            }
            if v.len() > 0 {
                return v;
            }

            self.buf_str.clear();
            self.reader
                .read_until(b'\n', &mut self.buf_str)
                .expect("Failed read");
            self.buf_iter = unsafe {
                let slice = std::str::from_utf8_unchecked(&self.buf_str);
                std::mem::transmute(slice.split_whitespace())
            }
        }
    }
}

fn lcm(first: usize, second: usize) -> usize {
    first * second / gcd(first, second)
}

fn gcd(first: usize, second: usize) -> usize {
    let mut max = first;
    let mut min = second;
    if min > max {
        let val = max;
        max = min;
        min = val;
    }

    loop {
        let res = max % min;
        if res == 0 {
            return min;
        }

        max = min;
        min = res;
    }
}
#[derive(Clone, Default, Debug)]
struct FactModCache<const MODVAL: i64> {
    fact: Vec<i64>,
    inv: Vec<i64>,
    n: i64,
}

impl<const MODVAL: i64> FactModCache<MODVAL> {
    fn new(n: usize) -> FactModCache<MODVAL> {
        let mut fmc = FactModCache {
            ..Default::default()
        };
        fmc.fact.resize(n, 0);
        fmc.inv.resize(n, 0);
        fmc.fact[0] = 1;
        fmc.inv[0] = 1;
        fmc.n = n as i64; //set this after so the calculation doesn't return cached value
        for i in 1..n {
            fmc.fact[i] = fmc.mult_mod(fmc.fact[i - 1], i as i64);
            fmc.inv[i] = fmc.inv_mod(fmc.fact[i]);
        }
        fmc
    }

    fn factorial_mod(&self, n: i64) -> i64 {
        if n < self.n {
            return self.fact[n as usize];
        }
        let mut t = self.fact[self.n as usize - 1];
        for x in self.n..=n {
            t = (t * x) % MODVAL;
        }
        t
    }

    fn permutations_mod(&self, n: i64, r: i64) -> i64 {
        let a = self.factorial_mod(n);
        let b = self.inv_fact_mod(n - r);
        return self.mult_mod(a, b);
    }

    fn inv_fact_mod(&self, n: i64) -> i64 {
        if n < self.n {
            return self.inv[n as usize];
        }
        self.pow_mod(self.factorial_mod(n), MODVAL - 2)
    }

    fn inv_mod(&self, n: i64) -> i64 {
        self.pow_mod(n, MODVAL - 2)
    }

    fn combinations_mod(&self, n: i64, r: i64) -> i64 {
        let a = self.factorial_mod(n);
        let b = self.inv_fact_mod(r);
        let c = self.inv_fact_mod(n - r);
        return self.mult_mod(self.mult_mod(a, b), c);
    }

    fn pow_mod(&self, mut base: i64, mut pow: i64) -> i64 {
        if pow == 0 {
            return 1;
        }
        let mut result = 1;
        while pow > 0 {
            if pow & 1 == 1 {
                result = (result * base) % MODVAL;
            }
            pow /= 2;
            base = (base * base) % MODVAL;
        }
        result
    }

    fn mult_mod(&self, a: i64, b: i64) -> i64 {
        let a = a as i128;
        let b = b as i128;
        ((a * b) % MODVAL as i128) as i64
    }

    fn add_mod(&self, a: i64, b: i64) -> i64 {
        ((a % MODVAL) + (b % MODVAL)) % MODVAL
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let stdout = io::stdout();
    let lock = stdout.lock();
    let stdin = io::stdin();
    let mut ow = io::BufWriter::new(lock);
    let mut scan = Scanner::new(stdin.lock());

    // let n_tests = scan.next::<i64>();
    let n_tests = 1;
    let fmc = FactModCache::<1000000007>::new(1000005);
    for t_num in 1..=n_tests {
        let n = scan.next::<usize>();
        let k = scan.next::<usize>();

        let mut start = 1;

        for i in 1..=(std::cmp::min(n, k)) {
            start = fmc.add_mod(start, fmc.combinations_mod(n as i64, i as i64));
        }

        writeln!(ow, "{}", start);
    }
    Ok(())
}

// start of input macros

macro_rules! input {
	(source = $s:expr, $($r:tt)*) => {
		let mut iter = $s.split_whitespace();
		input_inner!{iter, $($r)*}
	};
	($($r:tt)*) => {
		let s = {
			use std::io::Read;
			let mut s = String::new();
			std::io::stdin().read_to_string(&mut s).unwrap();
			s
		};
		let mut iter = s.split_whitespace();
		input_inner!{iter, $($r)*}
	};
}

macro_rules! input_inner {
	($iter:expr) => {};
	($iter:expr, ) => {};

	($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
		let $var = read_value!($iter, $t);
		input_inner!{$iter $($r)*}
	};
}

macro_rules! read_value {
	($iter:expr, ( $($t:tt),* )) => {
		( $(read_value!($iter, $t)),* )
	};

	($iter:expr, [ $t:tt ; $len:expr ]) => {
		(0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
	};

	($iter:expr, chars) => {
		read_value!($iter, String).chars().collect::<Vec<char>>()
	};

	($iter:expr, usize1) => {
		read_value!($iter, usize) - 1
	};

	($iter:expr, $t:ty) => {
		$iter.next().unwrap().parse::<$t>().expect("Parse error")
	};
}

// end of input macros

struct Factorial {
	n: usize,
	m: i64,
	factorial: Vec<i64>,
	inverse: Vec<i64>,
	inverse_factorial: Vec<i64>,
}

impl Factorial {
	fn new(n: usize, m: i64) -> Factorial {
		let mut factorial = vec![1; n + 1];
		let mut inverse = vec![1; n + 1];
		let mut inverse_factorial = vec![1; n + 1];
		for i in 2..=n {
			factorial[i] = (i as i64) * factorial[i - 1] % m;
			inverse[i] = ((m / (i as i64)) * -inverse[(m % (i as i64)) as usize] % m + m) % m;
			inverse_factorial[i] = inverse[i] * inverse_factorial[i - 1] % m;
		}
		Factorial {
			n,
			m,
			factorial,
			inverse,
			inverse_factorial,
		}
	}

	fn c(&self, n: usize, k: usize) -> i64 {
		if n < k {
			0
		} else {
			assert!(k <= n && n <= self.n);
			self.factorial[n] * self.inverse_factorial[k] % self.m * self.inverse_factorial[n - k]
				% self.m
		}
	}

	fn catalan(&self, n: usize) -> i64 {
		assert!(2 * n <= self.n);
		self.c(2 * n, n) * self.inverse[n + 1] % self.m
	}
}

// start of solution

const MOD: i64 = 1_000_000_007;

fn main() {
	input! {
	    n: usize, k: usize
	}
	let data = Factorial::new(200_005, MOD);
	let mut answer = 0;
	for i in 0..=n.min(k) {
	    answer = (answer + data.c(n, i)) % MOD;
	}
	println!("{}", answer);
}

// end of solution

pub mod solution {

use crate::io::input::Input;
use crate::io::output::output;
use crate::{out, out_line};
use std::cmp::min;
use crate::math::modular::factorial::Factorial;
use crate::math::modular::primitive::ModularType;

type Mod = ModularType<1000000007>;

fn solve(input: &mut Input, _test_case: usize) {
    let (n, k) = input.read();
    let mut ans = Mod::from(0);
    let factorials = Factorial::new(n);
    for i in 0..=min(k, n) {
        ans += factorials.combinations(n, i);
    }
    out_line!(ans);
}

pub(crate) fn run(mut input: Input) -> bool {
    solve(&mut input, 1);
    output().flush();
    input.skip_whitespace();
    !input.peek().is_some()
}

}
pub mod io {
pub mod input {
use std::fmt::Debug;
use std::io::Read;
use std::marker::PhantomData;
use std::str::FromStr;

pub struct Input<'s> {
    input: &'s mut dyn Read,
    buf: Vec<u8>,
    at: usize,
    buf_read: usize,
}

impl<'s> Input<'s> {
    const DEFAULT_BUF_SIZE: usize = 4096;

    pub fn new(input: &'s mut dyn Read) -> Self {
        Self {
            input,
            buf: vec![0; Self::DEFAULT_BUF_SIZE],
            at: 0,
            buf_read: 0,
        }
    }

    pub fn new_with_size(input: &'s mut dyn Read, buf_size: usize) -> Self {
        Self {
            input,
            buf: vec![0; buf_size],
            at: 0,
            buf_read: 0,
        }
    }

    pub fn get(&mut self) -> Option<u8> {
        if self.refill_buffer() {
            let res = self.buf[self.at];
            self.at += 1;
            Some(res)
        } else {
            None
        }
    }

    pub fn peek(&mut self) -> Option<u8> {
        if self.refill_buffer() {
            Some(self.buf[self.at])
        } else {
            None
        }
    }

    pub fn skip_whitespace(&mut self) {
        while let Some(b) = self.peek() {
            if !char::from(b).is_whitespace() {
                return;
            }
            self.get();
        }
    }

    pub fn next_token(&mut self) -> Option<Vec<u8>> {
        self.skip_whitespace();
        let mut res = Vec::new();
        while let Some(c) = self.get() {
            if char::from(c).is_whitespace() {
                break;
            }
            res.push(c);
        }
        if res.is_empty() {
            None
        } else {
            Some(res)
        }
    }

    //noinspection RsSelfConvention
    pub fn is_exhausted(&mut self) -> bool {
        self.peek().is_none()
    }

    pub fn read<T: Readable>(&mut self) -> T {
        T::read(self)
    }

    pub fn read_vec<T: Readable>(&mut self, size: usize) -> Vec<T> {
        let mut res = Vec::with_capacity(size);
        for _ in 0usize..size {
            res.push(self.read());
        }
        res
    }

    pub fn read_line(&mut self) -> String {
        let mut res = String::new();
        while let Some(c) = self.get() {
            if c == b'\n' {
                break;
            }
            if c == b'\r' {
                if self.peek() == Some(b'\n') {
                    self.get();
                }
                break;
            }
            res.push(c.into());
        }
        res
    }

    #[allow(clippy::should_implement_trait)]
    pub fn into_iter<T: Readable>(self) -> InputIterator<'s, T> {
        InputIterator {
            input: self,
            phantom: Default::default(),
        }
    }

    fn read_integer<T: FromStr>(&mut self) -> T
    where
        <T as FromStr>::Err: Debug,
    {
        let res = self.read_string();
        res.parse::<T>().unwrap()
    }

    fn read_string(&mut self) -> String {
        match self.next_token() {
            None => {
                panic!("Input exhausted");
            }
            Some(res) => unsafe { String::from_utf8_unchecked(res) },
        }
    }

    fn read_char(&mut self) -> char {
        self.skip_whitespace();
        self.get().unwrap().into()
    }

    fn read_float(&mut self) -> f64 {
        self.read_string().parse().unwrap()
    }

    fn refill_buffer(&mut self) -> bool {
        if self.at == self.buf_read {
            self.at = 0;
            self.buf_read = self.input.read(&mut self.buf).unwrap();
            self.buf_read != 0
        } else {
            true
        }
    }
}

pub trait Readable {
    fn read(input: &mut Input) -> Self;
}

impl Readable for String {
    fn read(input: &mut Input) -> Self {
        input.read_string()
    }
}

impl Readable for char {
    fn read(input: &mut Input) -> Self {
        input.read_char()
    }
}

impl Readable for f64 {
    fn read(input: &mut Input) -> Self {
        input.read_float()
    }
}

impl<T: Readable> Readable for Vec<T> {
    fn read(input: &mut Input) -> Self {
        let size = input.read();
        input.read_vec(size)
    }
}

pub struct InputIterator<'s, T: Readable> {
    input: Input<'s>,
    phantom: PhantomData<T>,
}

impl<'s, T: Readable> Iterator for InputIterator<'s, T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        self.input.skip_whitespace();
        self.input.peek().map(|_| self.input.read())
    }
}

macro_rules! read_integer {
    ($t:ident) => {
        impl Readable for $t {
            fn read(input: &mut Input) -> Self {
                input.read_integer()
            }
        }
    };
}

read_integer!(i8);
read_integer!(i16);
read_integer!(i32);
read_integer!(i64);
read_integer!(i128);
read_integer!(isize);
read_integer!(u8);
read_integer!(u16);
read_integer!(u32);
read_integer!(u64);
read_integer!(u128);
read_integer!(usize);

macro_rules! tuple_readable {
    ( $( $name:ident )+ ) => {
        impl<$($name: Readable), +> Readable for ($($name,)+) {
            fn read(input: &mut Input) -> Self {
                ($($name::read(input),)+)
            }
        }
    }
}

tuple_readable! {T}
tuple_readable! {T U}
tuple_readable! {T U V}
tuple_readable! {T U V X}
tuple_readable! {T U V X Y}
tuple_readable! {T U V X Y Z}
tuple_readable! {T U V X Y Z A}
tuple_readable! {T U V X Y Z A B}
tuple_readable! {T U V X Y Z A B C}
tuple_readable! {T U V X Y Z A B C D}
tuple_readable! {T U V X Y Z A B C D E}
tuple_readable! {T U V X Y Z A B C D E F}
}
pub mod output {
use std::io::Write;

pub struct Output {
    output: Box<dyn Write>,
    buf: Vec<u8>,
    at: usize,
    auto_flush: bool,
}

impl Output {
    const DEFAULT_BUF_SIZE: usize = 4096;

    pub fn new(output: Box<dyn Write>) -> Self {
        Self {
            output,
            buf: vec![0; Self::DEFAULT_BUF_SIZE],
            at: 0,
            auto_flush: false,
        }
    }

    pub fn new_with_auto_flush(output: Box<dyn Write>) -> Self {
        Self {
            output,
            buf: vec![0; Self::DEFAULT_BUF_SIZE],
            at: 0,
            auto_flush: true,
        }
    }

    pub fn flush(&mut self) {
        if self.at != 0 {
            self.output.write_all(&self.buf[..self.at]).unwrap();
            self.at = 0;
            self.output.flush().expect("Couldn't flush output");
        }
    }

    pub fn print<T: Writable>(&mut self, s: &T) {
        s.write(self);
    }

    pub fn put(&mut self, b: u8) {
        self.buf[self.at] = b;
        self.at += 1;
        if self.at == self.buf.len() {
            self.flush();
        }
    }

    pub fn maybe_flush(&mut self) {
        if self.auto_flush {
            self.flush();
        }
    }

    pub fn print_per_line<T: Writable>(&mut self, arg: &[T]) {
        for i in arg {
            i.write(self);
            self.put(b'\n');
        }
    }

    pub fn print_iter<T: Writable, I: Iterator<Item = T>>(&mut self, iter: I) {
        let mut first = true;
        for e in iter {
            if first {
                first = false;
            } else {
                self.put(b' ');
            }
            e.write(self);
        }
    }

    pub fn print_iter_ref<'a, T: 'a + Writable, I: Iterator<Item = &'a T>>(&mut self, iter: I) {
        let mut first = true;
        for e in iter {
            if first {
                first = false;
            } else {
                self.put(b' ');
            }
            e.write(self);
        }
    }
}

impl Write for Output {
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        let mut start = 0usize;
        let mut rem = buf.len();
        while rem > 0 {
            let len = (self.buf.len() - self.at).min(rem);
            self.buf[self.at..self.at + len].copy_from_slice(&buf[start..start + len]);
            self.at += len;
            if self.at == self.buf.len() {
                self.flush();
            }
            start += len;
            rem -= len;
        }
        if self.auto_flush {
            self.flush();
        }
        Ok(buf.len())
    }

    fn flush(&mut self) -> std::io::Result<()> {
        self.flush();
        Ok(())
    }
}

pub trait Writable {
    fn write(&self, output: &mut Output);
}

impl Writable for &str {
    fn write(&self, output: &mut Output) {
        output.write_all(self.as_bytes()).unwrap();
    }
}

impl Writable for String {
    fn write(&self, output: &mut Output) {
        output.write_all(self.as_bytes()).unwrap();
    }
}

impl Writable for char {
    fn write(&self, output: &mut Output) {
        output.put(*self as u8);
    }
}

impl<T: Writable> Writable for [T] {
    fn write(&self, output: &mut Output) {
        output.print_iter_ref(self.iter());
    }
}

impl<T: Writable> Writable for Vec<T> {
    fn write(&self, output: &mut Output) {
        self[..].write(output);
    }
}

macro_rules! write_to_string {
    ($t:ident) => {
        impl Writable for $t {
            fn write(&self, output: &mut Output) {
                self.to_string().write(output);
            }
        }
    };
}

write_to_string!(u8);
write_to_string!(u16);
write_to_string!(u32);
write_to_string!(u64);
write_to_string!(u128);
write_to_string!(usize);
write_to_string!(i8);
write_to_string!(i16);
write_to_string!(i32);
write_to_string!(i64);
write_to_string!(i128);
write_to_string!(isize);
write_to_string!(f32);
write_to_string!(f64);

impl<T: Writable, U: Writable> Writable for (T, U) {
    fn write(&self, output: &mut Output) {
        self.0.write(output);
        output.put(b' ');
        self.1.write(output);
    }
}

impl<T: Writable, U: Writable, V: Writable> Writable for (T, U, V) {
    fn write(&self, output: &mut Output) {
        self.0.write(output);
        output.put(b' ');
        self.1.write(output);
        output.put(b' ');
        self.2.write(output);
    }
}

pub static mut OUTPUT: Option<Output> = None;

pub fn output() -> &'static mut Output {
    unsafe {
        match &mut OUTPUT {
            None => {
                panic!("Panic");
            }
            Some(output) => output,
        }
    }
}

#[macro_export]
macro_rules! out {
    ($first: expr $(,$args:expr )*) => {
        output().print(&$first);
        $(output().put(b' ');
        output().print(&$args);
        )*
    }
}

#[macro_export]
macro_rules! out_line {
    ($first: expr $(, $args:expr )* ) => {
        out!($first $(,$args)*);
        output().put(b'\n');
    };
    () => {
        output().put(b'\n');
    };
}
}
}
pub mod math {
pub mod modular {
pub mod factorial {
use crate::math::modular::inverse::compute_inverse_up_to;
use crate::math::modular::primitive::Modular;

pub struct Factorial<Mod> {
    fact: Vec<Mod>,
    inverse_fact: Vec<Mod>,
}

impl<Mod> Factorial<Mod>
where
    Mod: Modular,
{
    pub fn new(n: usize) -> Self {
        let mut fact = vec![0.into(); n + 1];
        let mut inverse_fact = vec![0.into(); n + 1];
        let inv = compute_inverse_up_to(n);
        fact[0] = 1.into();
        inverse_fact[0] = 1.into();
        for i in 1..=n {
            fact[i] = fact[i - 1] * i.into();
            inverse_fact[i] = inverse_fact[i - 1] * inv[i];
        }
        Self { fact, inverse_fact }
    }

    pub fn combinations(&self, n: usize, k: usize) -> Mod {
        if k > n {
            0.into()
        } else {
            self.fact[n] * self.inverse_fact[n - k] * self.inverse_fact[k]
        }
    }
}
}
pub mod inverse {
use crate::math::modular::primitive::Modular;

pub fn compute_inverse_up_to<Mod>(n: usize) -> Vec<Mod>
where
    Mod: Modular,
{
    let mut inv: Vec<Mod> = vec![0.into(); n + 1];
    inv[1] = 1.into();
    for i in 2..=n {
        inv[i] = inv[Mod::MODULO as usize % i] * (Mod::MODULO as usize / i).into();
        inv[i] = -inv[i];
    }
    inv
}
}
pub mod primitive {
use crate::io::output::{Output, Writable};
use std::ops::{Add, AddAssign, Mul, Neg};

#[derive(Copy, Clone)]
pub struct ModularType<const M: u32>(u32);

pub trait Modular:
    Add<Output = Self>
    + AddAssign
    + Mul<Output = Self>
    + Neg<Output = Self>
    + From<usize>
    + From<i32>
    + From<u32>
    + Writable
    + Copy
{
    const MODULO: u32;
    fn value(&self) -> u32;
    fn usize(&self) -> usize {
        self.value() as usize
    }
}

impl<const M: u32> Modular for ModularType<M> {
    const MODULO: u32 = M;

    fn value(&self) -> u32 {
        self.0
    }
}

impl<const M: u32> Add for ModularType<M> {
    type Output = ModularType<M>;

    fn add(self, rhs: Self) -> Self::Output {
        let result = self.0 + rhs.0;
        ModularType(if result >= M { result - M } else { result })
    }
}

impl<const M: u32> AddAssign for ModularType<M> {
    fn add_assign(&mut self, rhs: Self) {
        self.0 += rhs.0;
        if self.0 >= M {
            self.0 -= M;
        }
    }
}

impl<const M: u32> Mul for ModularType<M> {
    type Output = ModularType<M>;

    fn mul(self, rhs: Self) -> Self::Output {
        Self((self.0 as u64 * rhs.0 as u64 % M as u64) as u32)
    }
}

impl<const M: u32> Neg for ModularType<M> {
    type Output = ModularType<M>;

    fn neg(self) -> Self::Output {
        Self(if self.0 == 0 { 0 } else { M - self.0 })
    }
}

impl<const M: u32> From<u32> for ModularType<M> {
    fn from(x: u32) -> Self {
        Self(x % M)
    }
}

impl<const M: u32> From<i32> for ModularType<M> {
    fn from(x: i32) -> Self {
        Self(x.rem_euclid(M as i32) as u32)
    }
}

impl<const M: u32> From<usize> for ModularType<M> {
    fn from(x: usize) -> Self {
        Self((x % M as usize) as u32)
    }
}

impl<const M: u32> Into<usize> for ModularType<M> {
    fn into(self) -> usize {
        self.0 as usize
    }
}

impl<const M: u32> Writable for ModularType<M> {
    fn write(&self, output: &mut Output) {
        self.0.write(output);
    }
}
}
}
}
fn main() {
    let mut sin = std::io::stdin();
    let input = crate::io::input::Input::new(&mut sin);
    unsafe {
        crate::io::output::OUTPUT = Some(crate::io::output::Output::new(Box::new(std::io::stdout())));
    }
    crate::solution::run(input);
}

#[allow(unused_imports)]
use std::{
    cmp,
    collections::{BinaryHeap, HashMap, HashSet, VecDeque},
    hash::Hash,
    io::{self, BufWriter, Read, StdoutLock, Write},
    str::Lines,
};

const MODVAL: u64 = 1e9 as u64 + 7;

#[allow(unused_mut, unused_variables)]
fn main() -> io::Result<()> {
    let mut input = String::new();
    io::stdin().lock().read_to_string(&mut input).unwrap();
    let mut input = input.lines();

    let out = io::stdout();
    let mut out = BufWriter::new(out.lock());

    let line = next_line_as_u64_vec(&mut input);
    let n = line[0];
    let k = line[1];

    let mut m = 1;
    for k in 1..=cmp::min(n, k) {
        m += bi_coefficient_mod(n, k, MODVAL);
    }
    writeln!(out, "{}", m)?;

    Ok(())
}

#[allow(dead_code)]
fn bi_coefficient_mod(n: u64, k: u64, modval: u64) -> u64 {
    if n == k {
        return 1;
    }
    let fact = FactorialsMod::new(n as usize, modval);
    let tmp = fact.get(n as usize).unwrap();
    let tmp = (tmp * mod_inverse(fact.get(k as usize).unwrap(), modval)) % modval;
    let tmp = (tmp * mod_inverse(fact.get((n - k) as usize).unwrap(), modval)) % modval;
    tmp
}

#[allow(dead_code)]
fn extended_euclidean(a: u64, b: u64) -> (u64, i64, i64) {
    fn rec(a: u64, b: u64, p: i64, q: i64, x: i64, y: i64) -> (u64, i64, i64) {
        if b == 0 {
            return (a, p, x);
        }
        let quot = (a / b) as i64;
        rec(b, a % b, q, p - quot * q, y, x - quot * y)
    }
    rec(a, b, 1, 0, 0, 1)
}

#[allow(dead_code)]
fn mod_inverse(n: u64, modval: u64) -> u64 {
    let (a, b) = if n > modval { (n, modval) } else { (modval, n) };
    let (gcd, x, y) = extended_euclidean(a, b);
    assert!(gcd == 1, "gcd({},{}) is not zero!", a, modval);
    let m = modval as i64;
    let res = if n > modval {
        ((x % m + m) % m) as u64
    } else {
        ((y % m + m) % m) as u64
    };
    res
}

#[derive(Debug, Clone)]
struct FactorialsMod {
    numbers: Vec<u64>,
    current: usize,
}

#[allow(dead_code)]
impl FactorialsMod {
    fn new(n: usize, modval: u64) -> Self {
        let mut numbers = vec![0; n + 1];
        let mut fac = 1u64;
        for i in 1..=n {
            fac *= i as u64;
            fac %= modval;
            numbers[i] = fac;
        }
        let current = 0;
        FactorialsMod { numbers, current }
    }

    fn reset(&mut self) {
        self.current = 0;
    }

    fn get(&self, n: usize) -> Option<u64> {
        self.numbers.get(n).map(|&x| x)
    }
}

impl Iterator for FactorialsMod {
    type Item = u64;
    fn next(&mut self) -> Option<Self::Item> {
        if self.current == self.numbers.len() {
            return None;
        }
        self.current += 1;
        self.numbers.get(self.current).map(|n| *n)
    }
}

#[allow(dead_code)]
fn next_line(input: &mut Lines) -> String {
    input.next().unwrap().to_string()
}

#[allow(dead_code)]
fn next_line_as_u64(input: &mut Lines) -> u64 {
    let s = input.next().unwrap();
    let n: u64 = s.parse().unwrap();
    n
}

#[allow(dead_code)]
fn next_line_as_i64(input: &mut Lines) -> i64 {
    let s = input.next().unwrap();
    let n: i64 = s.parse().unwrap();
    n
}

#[allow(dead_code)]
fn next_line_as_string_vec(input: &mut Lines) -> Vec<String> {
    let s = input.next().unwrap();
    let a = s.split(" ").collect::<Vec<&str>>();
    a.iter().map(|&s| s.to_string()).collect()
}

#[allow(dead_code)]
fn next_line_as_char_vec(input: &mut Lines) -> Vec<char> {
    let s = input.next().unwrap();
    let a: Vec<char> = s.chars().collect();
    a
}

#[allow(dead_code)]
fn next_line_as_u64_vec(input: &mut Lines) -> Vec<u64> {
    let s = input.next().unwrap();
    let a: Vec<u64> = s.split(" ").map(|s| s.parse().unwrap()).collect();
    a
}

#[allow(dead_code)]
fn next_line_as_i64_vec(input: &mut Lines) -> Vec<i64> {
    let s = input.next().unwrap();
    let a: Vec<i64> = s.split(" ").map(|s| s.parse().unwrap()).collect();
    a
}

#[allow(dead_code)]
fn write_bool_answer(answer: bool, out: &mut BufWriter<StdoutLock>) {
    if answer {
        writeln!(out, "yes").unwrap();
    } else {
        writeln!(out, "no").unwrap();
    }
}

#[allow(unused_imports)]
use std::{
    cmp,
    collections::{BinaryHeap, HashMap, HashSet, VecDeque},
    hash::Hash,
    io::{self, BufWriter, Read, StdoutLock, Write},
    str::Lines,
};

#[allow(unused_mut, unused_variables)]
fn main() -> io::Result<()> {
    let mut input = String::new();
    io::stdin().lock().read_to_string(&mut input).unwrap();
    let mut input = input.lines();

    let out = io::stdout();
    let mut out = BufWriter::new(out.lock());

    let line = next_line_as_u64_vec(&mut input);
    let n = line[0] as u32;
    let k = line[1] as u32;

    let stop = cmp::min(n, k);
    let mut winner = 1u64;
    for i in 1..=stop {
        winner += 2u64.pow(n - i);
    }

    let answer = winner % (1_000_000_000 + 7);
    println!("{}", answer);

    Ok(())
}

#[allow(dead_code)]
fn next_line(input: &mut Lines) -> String {
    input.next().unwrap().to_string()
}

#[allow(dead_code)]
fn next_line_as_u64(input: &mut Lines) -> u64 {
    let s = input.next().unwrap();
    let n: u64 = s.parse().unwrap();
    n
}

#[allow(dead_code)]
fn next_line_as_i64(input: &mut Lines) -> i64 {
    let s = input.next().unwrap();
    let n: i64 = s.parse().unwrap();
    n
}

#[allow(dead_code)]
fn next_line_as_string_vec(input: &mut Lines) -> Vec<String> {
    let s = input.next().unwrap();
    let a = s.split(" ").collect::<Vec<&str>>();
    a.iter().map(|&s| s.to_string()).collect()
}

#[allow(dead_code)]
fn next_line_as_char_vec(input: &mut Lines) -> Vec<char> {
    let s = input.next().unwrap();
    let a: Vec<char> = s.chars().collect();
    a
}

#[allow(dead_code)]
fn next_line_as_u64_vec(input: &mut Lines) -> Vec<u64> {
    let s = input.next().unwrap();
    let a: Vec<u64> = s.split(" ").map(|s| s.parse().unwrap()).collect();
    a
}

#[allow(dead_code)]
fn next_line_as_i64_vec(input: &mut Lines) -> Vec<i64> {
    let s = input.next().unwrap();
    let a: Vec<i64> = s.split(" ").map(|s| s.parse().unwrap()).collect();
    a
}

#[allow(dead_code)]
fn write_bool_answer(answer: bool, out: &mut BufWriter<StdoutLock>) {
    if answer {
        writeln!(out, "yes").unwrap();
    } else {
        writeln!(out, "no").unwrap();
    }
}

#![allow(dead_code, unused_macros, unused_imports)]
use std::cell::RefCell;
use std::cmp::Ordering;
use std::collections::*;
use std::error::Error;
use std::fmt::write;
use std::hash::Hash;
use std::io;
use std::io::prelude::*;
use std::io::StdinLock;
use std::io::StdoutLock;
use std::io::Write;
use std::io::{stdin, stdout, BufRead, BufWriter};
use std::ops::Add;
use std::thread::panicking;

macro_rules! fprintvec {
    ($dst:expr, $arg:expr) => {{
        writeln!(
            $dst,
            "{}",
            $arg.iter()
                .map(|x| format!("{} ", x))
                .collect::<Vec<String>>()
                .join("")
        )
        .ok();
    }};
}

pub struct Scanner<B> {
    reader: B,
    buf_str: Vec<u8>,
    buf_iter: std::str::SplitWhitespace<'static>,
}
impl<B: BufRead> Scanner<B> {
    pub fn new(reader: B) -> Self {
        Self {
            reader,
            buf_str: Vec::new(),
            buf_iter: "".split_whitespace(),
        }
    }
    pub fn next<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buf_iter.next() {
                return token.parse().ok().expect("Failed parse");
            }
            self.buf_str.clear();
            self.reader
                .read_until(b'\n', &mut self.buf_str)
                .expect("Failed read");
            self.buf_iter = unsafe {
                let slice = std::str::from_utf8_unchecked(&self.buf_str);
                std::mem::transmute(slice.split_whitespace())
            }
        }
    }

    pub fn next_split<T: std::str::FromStr>(&mut self) -> Vec<T> {
        loop {
            let mut v = Vec::new();
            while let Some(token) = self.buf_iter.next() {
                v.push(token.parse().ok().expect("Failed parse"));
            }
            if v.len() > 0 {
                return v;
            }

            self.buf_str.clear();
            self.reader
                .read_until(b'\n', &mut self.buf_str)
                .expect("Failed read");
            self.buf_iter = unsafe {
                let slice = std::str::from_utf8_unchecked(&self.buf_str);
                std::mem::transmute(slice.split_whitespace())
            }
        }
    }
}
fn lcm(first: usize, second: usize) -> usize {
    first * second / gcd(first, second)
}

fn gcd(first: usize, second: usize) -> usize {
    let mut max = first;
    let mut min = second;
    if min > max {
        let val = max;
        max = min;
        min = val;
    }

    loop {
        let res = max % min;
        if res == 0 {
            return min;
        }

        max = min;
        min = res;
    }
}
const MOD_VAL: i64 = 1000000007;
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let stdout = io::stdout();
    let lock = stdout.lock();
    let stdin = io::stdin();
    let mut ow = io::BufWriter::new(lock);
    let mut scan = Scanner::new(stdin.lock());

    // let n_tests = scan.next::<i64>();
    let n_tests = 1;
    for t_num in 1..=n_tests {
        let n = scan.next::<usize>();
        let k = scan.next::<usize>();

        let mut start = 1;
        let mut step = 1;
        let good;
        if n >= k {
            good = n - k;
        } else {
            good = 0;
        }
        for i in 0..good {
            step = (step * 2) % MOD_VAL;
        }
        for i in 0..k {
            start = ((start % MOD_VAL) + (step % MOD_VAL)) % MOD_VAL;
            step = (step * 2) % MOD_VAL;
        }
        writeln!(ow, "{}", start);
    }
    Ok(())
}

// start of input macros

macro_rules! input {
	(source = $s:expr, $($r:tt)*) => {
		let mut iter = $s.split_whitespace();
		input_inner!{iter, $($r)*}
	};
	($($r:tt)*) => {
		let s = {
			use std::io::Read;
			let mut s = String::new();
			std::io::stdin().read_to_string(&mut s).unwrap();
			s
		};
		let mut iter = s.split_whitespace();
		input_inner!{iter, $($r)*}
	};
}

macro_rules! input_inner {
	($iter:expr) => {};
	($iter:expr, ) => {};

	($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
		let $var = read_value!($iter, $t);
		input_inner!{$iter $($r)*}
	};
}

macro_rules! read_value {
	($iter:expr, ( $($t:tt),* )) => {
		( $(read_value!($iter, $t)),* )
	};

	($iter:expr, [ $t:tt ; $len:expr ]) => {
		(0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
	};

	($iter:expr, chars) => {
		read_value!($iter, String).chars().collect::<Vec<char>>()
	};

	($iter:expr, usize1) => {
		read_value!($iter, usize) - 1
	};

	($iter:expr, $t:ty) => {
		$iter.next().unwrap().parse::<$t>().expect("Parse error")
	};
}

// end of input macros

struct Factorial {
	n: usize,
	m: i64,
	factorial: Vec<i64>,
	inverse: Vec<i64>,
	inverse_factorial: Vec<i64>,
}

impl Factorial {
	fn new(n: usize, m: i64) -> Factorial {
		let mut factorial = vec![1; n + 1];
		let mut inverse = vec![1; n + 1];
		let mut inverse_factorial = vec![1; n + 1];
		for i in 2..=n {
			factorial[i] = (i as i64) * factorial[i - 1] % m;
			inverse[i] = ((m / (i as i64)) * -inverse[(m % (i as i64)) as usize] % m + m) % m;
			inverse_factorial[i] = inverse[i] * inverse_factorial[i - 1] % m;
		}
		Factorial {
			n,
			m,
			factorial,
			inverse,
			inverse_factorial,
		}
	}

	fn c(&self, n: usize, k: usize) -> i64 {
		if n < k {
			0
		} else {
			assert!(k <= n && n <= self.n);
			self.factorial[n] * self.inverse_factorial[k] % self.m * self.inverse_factorial[n - k]
				% self.m
		}
	}

	fn catalan(&self, n: usize) -> i64 {
		assert!(2 * n <= self.n);
		self.c(2 * n, n) * self.inverse[n + 1] % self.m
	}
}

// start of solution

const MOD: i64 = 998_244_353;

fn main() {
	input! {
	    n: usize, k: usize
	}
	let data = Factorial::new(200_005, MOD);
	let mut answer = 0;
	for i in 0..=n.min(k) {
	    answer = (answer + data.c(n, i)) % MOD;
	}
	println!("{}", answer);
}

// end of solution