Madoka decided to entrust the organization of a major computer game tournament "OSU"!In this tournament, matches are held according to the "Olympic system". In other words, there are $$$2^n$$$ participants in the tournament, numbered with integers from $$$1$$$ to $$$2^n$$$. There are $$$n$$$ rounds in total in the tournament. In the $$$i$$$-th round there are $$$2^{n - i}$$$ matches between two players (one of whom is right, the other is left), after which the winners go further along the tournament grid, and the losing participants are eliminated from the tournament. Herewith, the relative order in the next round does not change. And the winner of the tournament — is the last remaining participant.But the smaller the participant's number, the more he will pay Madoka if he wins, so Madoka wants the participant with the lowest number to win. To do this, she can arrange the participants in the first round as she likes, and also determine for each match who will win — the participant on the left or right.But Madoka knows that tournament sponsors can change the winner in matches no more than $$$k$$$ times. (That is, if the participant on the left won before the change, then the participant on the right will win after the change, and if the participant on the right won, then the participant on the left will win after the change).  So, the first image shows the tournament grid that Madoka made, where the red lines denote who should win the match. And the second one shows the tournament grid, after one change in the outcome of the match by sponsors (a match between $$$1$$$ and $$$3$$$ players). Print the minimum possible number of the winner in the tournament, which Madoka can get regardless of changes in sponsors. But since the answer can be very large, output it modulo $$$10^9 + 7$$$. Note that we need to minimize the answer, and only then take it modulo.

The first and the only line contains two integers $$$n$$$ and $$$k$$$ ($$$1 \le n \le 10^5, 1 \le k \le \min(2^n - 1, 10^9)$$$) — the number of rounds in the tournament and the number of outcomes that sponsors can change.

Print exactly one integer — the minimum number of the winner modulo $$$10^9 + 7$$$

NoteIn the first example, there is only one match between players $$$1$$$ and $$$2$$$, so the sponsors can always make player $$$2$$$ wins.The tournament grid from the second example is shown in the picture in the statement.

#[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);
}

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