//spnauti-rust
use std::io::*;
use std::str::*;
use std::fmt::Debug;
#[allow(unused_imports)] use std::cmp::Ordering::*;
#[allow(unused_imports)] use std::collections::*;

#[allow(unused_macros)]
macro_rules! a {
    ($c: tt, $x: expr, $y: expr) => {{
        let b = $y; let a = &mut $x;
        if b $c *a { *a = b; true } else { false }
    }};
}
struct WordReader<'a> { it : SplitAsciiWhitespace<'a>, }
#[allow(dead_code)]
impl<'a> WordReader<'a> {
    fn new<T: Read>(b: &mut String, mut r: T) -> WordReader {
        b.clear();
        r.read_to_string(b).unwrap();
        WordReader { it: b.split_ascii_whitespace() }
    }
    fn from_stdin(b: &mut String) -> WordReader {
        WordReader::new(b, stdin())
    }
    fn sl(&mut self) ->  &str { self.it.next().unwrap() }
    fn bs(&mut self) -> &[u8] { self.sl().as_bytes()    }
    fn s(&mut self) -> String { String::from(self.sl()) }
    fn i(&mut self) ->    i32 { self.p()                }
    fn u(&mut self) ->  usize { self.p()                }
    fn vi(&mut self, n: usize) -> Vec<i32> {
        self.vp::<i32>(n)
    }
    fn p<T: FromStr>(&mut self) -> T where T::Err: Debug {
        self.sl().parse::<T>().unwrap()
    }
    fn vp<T: FromStr>(&mut self, n: usize) -> Vec<T> where T::Err: Debug {
        (0..n).map(|_| self.p()).collect()
    }
}

#[allow(dead_code)]
fn build_counting_hashmap<K: Eq + std::hash::Hash, T>(i: T) -> HashMap<K,usize>
    where T: Iterator<Item = K> {
    let mut m = HashMap::new();
    for k in i {
        let n = 1 + if let Some(&n) = m.get(&k) { n } else { 0 };
        m.insert(k, n);
    }
    m
}

fn main() {
    let mut bin = String::new();
    let mut input = WordReader::from_stdin(&mut bin);

    let _ = input.i();
    let x = vec![7,5,3,2];
    let mut a = vec![0; 4];
    for c in input.bs() {
        for mut z in 2..(c - b'0' + 1) as i32 {
            for j in 0..4 {
                while z % x[j] == 0 {
                    z /= x[j];
                    a[j] += 1;
                }
            }
        }
    }
    for i in 0..4 {
        let n = a[i];
        for _ in 0..n { print!("{}", x[i]); }
        for mut z in 2..x[i] + 1 {
            for j in 0..4 {
                while z % x[j] == 0 {
                    z /= x[j];
                    a[j] -= n;
                }
            }
        }
    }
}


use std::io;

fn run(s: String){
    let mut arr: [usize;10] = [0;10];

    for c in s.chars(){
        let mut x=(c.to_string()).parse::<usize>().unwrap();
        if x==4 || x==8 || x==6 ||x==9{
            if x==4{
                arr[2]+=2;
            }
            else if x==8{
                arr[2]+=3;
            }
            else if x==6{
                arr[3]+=1;
            }
            else{
                arr[2]+=1;
                arr[3]+=2;
                x-=1;
            }
            x-=1;
        }
        arr[x]+=1;
    }
    for i in (2..10).rev(){
        for _j in 0..arr[i]{
            print!("{}",i);
        }
    }
}
fn main()
{
    let mut s1=String::new();
    let mut s2=String::new();
    io::stdin().read_line(&mut s1).expect("read error");
    io::stdin().read_line(&mut s2).expect("read error");

    run(s2.trim().to_string());
}


use std::io::Read;

fn input(read_file: bool) -> String {
    if read_file {
        let mut file = std::fs::File::open("sample.txt").unwrap();
        let mut buf = String::new();
        file.read_to_string(&mut buf).unwrap();
        buf
    } else {
        let mut buf = String::new();
        std::io::stdin().read_to_string(&mut buf).unwrap();
        buf.trim_end().to_owned()
    }
}

fn solve(ws: &mut std::str::SplitWhitespace) {
    let _: usize = ws.next().unwrap().parse().unwrap();
    let s: Vec<char> = ws.next().unwrap().to_string().chars().collect();

    let mut m = std::collections::HashMap::new();
    m.insert(2, "2");
    m.insert(3, "3");
    m.insert(4, "223");
    m.insert(5, "5");
    m.insert(6, "35");
    m.insert(7, "7");
    m.insert(8, "2227");
    m.insert(9, "2337");

    let mut ans: Vec<char> = Vec::new();
    for c in s {
        let d = c as i32 - '0' as i32;
        let mut x: Vec<char> = m.entry(d).or_default().chars().collect();
        ans.append(&mut x);
    }

    ans.sort();
    ans.reverse();
    let s: String = ans.iter().collect();
    println!("{}", s);
}

fn main() {
    const READ_FROM_FILE: bool = false;

    let s = input(READ_FROM_FILE);
    let mut ws = s.split_whitespace();

    solve(&mut ws);
}


use std::io::stdin;

fn main() {
    stdin().read_line(&mut String::new());

    let mut a = String::new();
    stdin().read_line(&mut a).unwrap();
    let a = a.trim();

    let a: Vec<char> = a
        .chars()
        .filter(|x| x != &'0' && x != &'1')
        .collect();

    let mut c = String::new();

    for i in a {
        let b = i.to_string();
        let b = b.as_str();
        c.push_str( match i {
            '4' => "223",
            '6' => "53",
            '8' => "7222",
            '9' => "2337",
            _ => b
        });
    }

    let mut c: Vec<u32> = c.chars().map(|x| x.to_digit(10 as u32).unwrap()).collect();

    c.sort();
    c.reverse();

    for i in c {
        print!("{}", i);
    }
    println!();
}


use std::io::prelude::*;
use std::io;
use std::str::FromStr;
#[cfg(local)]
use std::fs::File;
#[cfg(local)]
use std::io::BufReader;

use std::cmp;

#[cfg(local)]
fn buf_read() -> io::Result<(Vec<String>)> {
    let f = try!(File::open("input.txt"));
    let input_lines: Vec<_> = BufReader::new(f).lines().collect();
    let lines: Vec<String> = input_lines.into_iter().map(|e| e.unwrap()).collect();
    Ok((lines))
}

#[cfg(not(local))]
fn buf_read() -> io::Result<(Vec<String>)> {
    let stdin = io::stdin();
    let input_lines: Vec<_> = stdin.lock().lines().collect();
    let lines: Vec<String> = input_lines.into_iter().map(|e| e.unwrap()).collect();
    Ok((lines))
}

fn main() {
    type Element = i64;
    let input = buf_read().unwrap();
    let mut input_vectors: Vec<Vec<Element>> = vec![];
    for input_line in input {
        let input_str: Vec<String> = input_line.split(' ').map(String::from).collect();
        let mut input_vector: Vec<Element> = vec![];
        for input_elem_str in input_str {
            let elem: Element = Element::from_str(input_elem_str.as_str()).unwrap();
            input_vector.push(elem);
        }
        input_vectors.push(input_vector);
    }
    let k = input_vectors[0][0];
    let a = input_vectors[0][1];
    let b = input_vectors[0][2];
    let c = input_vectors[0][3];
    let required_copies = match k % 4 {
        0 => 0,
        n => 4 - n,
    };
    let cost = match required_copies {
        1 => cmp::min(a * 1, cmp::min(b * 1 + c * 1, c * 3)),
        2 => cmp::min(cmp::min(a * 2, b * 1), cmp::min(a * 1 + c * 1, c * 2)),
        3 => cmp::min(a * 3, cmp::min(a * 1 + b * 1, c * 1)),
        _ => 0,
    };
    println!("{}", cost);
}


use std::io::{self, Stdin};
use std::str::{self, FromStr};
use std::error::Error;
use std::thread;
use std::cmp::*;
fn exec() {
    let mut sc = Scanner::new();
    let n: usize = sc.ne();
    let a: usize = sc.ne();
    let b: usize = sc.ne();
    let c: usize = sc.ne();
    let ans = match n % 4 {
        0 => 0,
        1 => min(a * 3, min(a + b, c)),
        2 => min(a * 2, min(c * 2, b)),
        _ => min(a, min(b + c, c * 3)),
    };
    println!("{}", ans);
}

fn main() {
    const DEFAULT_STACK: usize = 16 * 1024 * 1024;
    let builder = thread::Builder::new();
    let th = builder.stack_size(DEFAULT_STACK);
    let handle = th.spawn(|| { exec(); }).unwrap();
    let _ = handle.join();
}

#[allow(dead_code)]
struct Scanner {
    stdin: Stdin,
    id: usize,
    buf: Vec<u8>,
}

#[allow(dead_code)]
impl Scanner {
    fn new() -> Scanner {
        Scanner {
            stdin: io::stdin(),
            id: 0,
            buf: Vec::new(),
        }
    }
    fn next_line(&mut self) -> Option<String> {
        let mut res = String::new();
        match self.stdin.read_line(&mut res) {
            Ok(0) => return None,
            Ok(_) => Some(res),
            Err(why) => panic!("error in read_line: {}", why.description()),
        }
    }
    fn next<T: FromStr>(&mut self) -> Option<T> {
        while self.buf.len() == 0 {
            self.buf = match self.next_line() {
                Some(r) => {
                    self.id = 0;
                    r.trim().as_bytes().to_owned()
                }
                None => return None,
            };
        }
        let l = self.id;
        assert!(self.buf[l] != b' ');
        let n = self.buf.len();
        let mut r = l;
        while r < n && self.buf[r] != b' ' {
            r += 1;
        }
        let res = match str::from_utf8(&self.buf[l..r]).ok().unwrap().parse::<T>() {
            Ok(s) => Some(s),
            Err(_) => panic!("parse error"),
        };
        while r < n && self.buf[r] == b' ' {
            r += 1;
        }
        if r == n {
            self.buf.clear();
        } else {
            self.id = r;
        }
        res
    }
    fn ne<T: FromStr>(&mut self) -> T {
        self.next::<T>().unwrap()
    }
}


use std::io::stdin;
use std::cmp::min;

fn main() {
    let mut input_line = String::new();
    stdin().read_line(&mut input_line);

    let input_iter = input_line.
        split_whitespace().
        map(|x| x.parse::<u64>().unwrap());

    let input: Vec<_> = input_iter.collect();

    let owned = input[0];
    if owned % 4 == 0 {
        // Already meet criteria
        println!("0");
        return;
    }

    let purchase = (4 - owned % 4) as usize;

    let mut dp = vec![u64::max_value(); 12];
    dp[0] = 0;

    for i in 0..12 {
        for j in 1..4 {
            if i >= j {
                dp[i] = min(dp[i - j] + input[j], dp[i]);
            }
        }
    }

    println!("{}", min(min(dp[purchase], dp[purchase + 4]), dp[purchase + 8]));
}


use std::io::stdin;
use std::cmp::min;

fn main() {
    let mut input_line = String::new();
    stdin().read_line(&mut input_line);

    let mut input_iter = input_line.
        split_whitespace().
        map(|x| x.parse::<u64>().unwrap());

    let owned = input_iter.next().unwrap();
    let price1 = input_iter.next().unwrap();
    let price2 = input_iter.next().unwrap();
    let price3 = input_iter.next().unwrap();

    if owned % 4 == 0 {
        // Already meet criteria
        println!("0");
        return;
    }

    let purchase = 4 - owned % 4;
    let result = match purchase {
        1 => min(price1, min(price3 * 3, price2 + price3)),
        2 => min(price2, min(price1 * 2, price3 * 2)),
        3 => min(price3, min(price1 * 3, price2 + price1)),
        _ => u64::max_value()
    };

    println!("{}", result);
}


fn main() {
	let inp = std::io::stdin();
	let mut inp = my_ios::InputReader::new(inp.lock());
	let m:i64 = 1000000007;
	let n:i64 = inp.read();
	let _l:i64 = inp.read();
	let l = _l - 1;
	let r:i64 = inp.read();
	let mut cnt = vec![0 as i64; 3];
	for i in 0..3 {
		cnt[i] += r / 3 + m - l / 3;
		if i as i64 <= r % 3 {
			cnt[i] += 1;
		}
		if i as i64 <= l % 3 {
			cnt[i] += m - 1;
		}
		cnt[i] %= m;
	}
	let mut dp = vec![0 as i64; 3];
	let mut tp = vec![0 as i64; 3];
	dp[0] = 1;
	for _ in 0..n {
		for i in 0..3 {
			for j in 0..3 {
				tp[(i + j) % 3] += dp[i] * cnt[j];
			}
		}
		for i in 0..3 {
			tp[i] %= m;
			dp[i] = tp[i];
			tp[i] = 0;
		}
	}
	println!("{}", dp[0]);
}

mod my_ios {
	use std::io::{BufRead, ErrorKind, Result};
	use std::str::{FromStr, from_utf8};
	use std::fmt::Debug;

	pub fn read_token<R:BufRead>(r:&mut R, buf:&mut Vec<u8>) -> Result<usize> {
		let mut read = 0;
		loop {
			let (done, used) = {
				let avail = match r.fill_buf() {
					Ok(n) => n,
					Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
					Err(e) => return Err(e)
				};
				match avail.iter().position(|&x| x == b'\n' || x== b' ') {
					Some(i) => {
						buf.extend_from_slice(&avail[..i]);
						(true, i + 1)
					}
					None => {
						buf.extend_from_slice(avail);
						(false, avail.len())
					}
				}
			};
			r.consume(used);
			read += used;
			if done || used == 0 {
				return Ok(read);
			}
		}
	}

	pub struct InputReader<R:BufRead> {
		reader:R,
		buf:Vec<u8>,
	}

	impl<R:BufRead> InputReader<R> {
		pub fn new(reader: R) -> InputReader<R> {
			InputReader {
				reader:reader,
				buf:Vec::<u8>::new(),
			}
		}
		pub fn read_token(&mut self) {
			read_token(&mut self.reader, &mut self.buf);
		}
		pub fn read<T>(&mut self) -> T where T:FromStr, T::Err:Debug {
			self.buf.clear();
			self.read_token();
			from_utf8(&self.buf).unwrap().trim().parse().unwrap()
		}
	}
}


use std::io::{self, BufWriter, Write};
use std::str::{self, SplitAsciiWhitespace};

// I have no idea what I'm doing

fn main() -> Result<(), io::Error> {
    let (stdin, stdout) = (io::stdin(), io::stdout());
    let mut scan = UnsafeScanner::new(stdin.lock());
    let mut out = BufWriter::new(stdout.lock());

    let n: usize = scan.token();
    let (l, r) = scan.pair::<i64>();

    const M: i64 = 1_000_000_007;

    let m0 = r/3 - (l-1)/3;
    let m1 = m0
             - if r%3 == 0 { 1 } else { 0 }
             + if (l-1)%3 == 0 { 1 } else { 0 };
    let m2 = m0
             - if r%3 <= 1 { 1 } else { 0 }
             + if (l-1)%3 <= 1 { 1 } else { 0 };

    dbg!(m0);
    dbg!(m1);
    dbg!(m2);

    let mut ans = [1_i64, 0, 0];
    for _ in 0..n {
        let mut nxt = [0_i64; 3];
        nxt[0] = m0 * ans[0] % M + m1 * ans[2] % M + m2 * ans[1];
        nxt[1] = m0 * ans[1] % M + m1 * ans[0] % M + m2 * ans[2];
        nxt[2] = m0 * ans[2] % M + m1 * ans[1] % M + m2 * ans[0];

        for i in 0..3 {
            ans[i] = nxt[i] % M;
        }
    }

    writeln!(out, "{}", ans[0])?;

    Ok(())
}

///////////////////////////////////////////////////////////////////////////////////////////////////

/// Copied from https://github.com/EbTech/rust-algorithms/blob/master/src/scanner.rs
/// Same API as Scanner but nearly twice as fast, using horribly unsafe dark arts
/// **REQUIRES** Rust 1.34 or higher
pub struct UnsafeScanner<R> {
    reader: R,
    buf_str: Vec<u8>,
    buf_iter: SplitAsciiWhitespace<'static>,
}

impl<R: io::BufRead> UnsafeScanner<R> {
    pub fn new(reader: R) -> Self {
        Self {
            reader,
            buf_str: vec![],
            buf_iter: "".split_ascii_whitespace(),
        }
    }

    /// This function should be marked unsafe, but noone has time for that in a
    /// programming contest. Use at your own risk!
    pub fn token<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_ascii_whitespace())
            }
        }
    }

    pub fn pair<T: str::FromStr>(&mut self) -> (T, T) {
        (self.token(), self.token())
    }
}


use std::io;

fn main() {
    let mut input = String::new();
    io::stdin().read_line(&mut input).expect("ERROR: Empty input.");
    let mut words = input.split_whitespace();
    let k:u64 = words.next().expect("k not given.").parse().unwrap();
    let p:u64 = words.next().expect("p not given.").parse().unwrap();

    let mut sum:u64 = 0;
    for i in 1..k+1 {
        sum+=zcy(i);
        //println!("zcy({}) = {}",i,zcy(i));
    }

    //println!("{} % {}",sum,p);
    println!("{}",sum % p);
}

fn rev(n:u64) -> u64 {
    let mut rev:u64 = 0;
    let mut n = n;
    while n>0 {
        rev*=10;
        rev+=n%10;
        n/=10;
    }
    return rev;
}

fn num_digits(n:u64) -> u32 {
    let mut d:u32 = 0;
    let mut n = n;
    while n>0 {
        n/=10;
        d+=1;
    }
    return d;
}

fn zcy(n:u64) -> u64{
    n*(10u64.pow(num_digits(n)))+rev(n)
}


fn main() {
    let mut stdin = String::new();
    std::io::Read::read_to_string(&mut std::io::stdin(), &mut stdin).unwrap();
    let mut stdin = stdin.split_whitespace();
    let mut get = || stdin.next().unwrap();
    macro_rules! get { () => (get().parse().unwrap()) }

    let k: u64 = get!();
    let p: u64 = get!();
    let mut ans: u64 = 0;
    for i in 1..k+1 {
        let mut x = i;
        let mut y = i;
        let mut r = 0;
        while x > 0 {
            r = r * 10 + x % 10;
            x /= 10;
            y *= 10;
        }
        ans = (y + r + ans) % p;
    }
    println!("{}", ans);
}


#[allow(unused_imports)]
use std::cmp::{max, min, Ordering};
#[allow(unused_imports)]
use std::collections::{HashMap, HashSet, BinaryHeap, VecDeque, BTreeSet, BTreeMap};
#[allow(unused_imports)]
use std::iter::FromIterator;
#[allow(unused_imports)]
use std::io::stdin;

mod util {
    use std::io::stdin;
    use std::str::FromStr;
    use std::fmt::Debug;

    #[allow(dead_code)]
    pub fn line() -> String {
        let mut line: String = String::new();
        stdin().read_line(&mut line).unwrap();
        line.trim().to_string()
    }

    #[allow(dead_code)]
    pub fn gets<T: FromStr>() -> Vec<T>
    where
        <T as FromStr>::Err: Debug,
    {
        let mut line: String = String::new();
        stdin().read_line(&mut line).unwrap();
        line.split_whitespace()
            .map(|t| t.parse().unwrap())
            .collect()
    }
}

#[allow(unused_macros)]
macro_rules! get {
    ($t:ty) => {
        {
            let mut line: String = String::new();
            stdin().read_line(&mut line).unwrap();
            line.trim().parse::<$t>().unwrap()
        }
    };
    ($($t:ty),*) => {
        {
            let mut line: String = String::new();
            stdin().read_line(&mut line).unwrap();
            let mut iter = line.split_whitespace();
            (
                $(iter.next().unwrap().parse::<$t>().unwrap(),)*
            )
        }
    };
    ($t:ty; $n:expr) => {
        (0..$n).map(|_|
                    get!($t)
                   ).collect::<Vec<_>>()
    };
    ($($t:ty),*; $n:expr) => {
        (0..$n).map(|_|
                    get!($($t),*)
                   ).collect::<Vec<_>>()
    };
    ($t:ty ;;) => {
        {
            let mut line: String = String::new();
            stdin().read_line(&mut line).unwrap();
            line.split_whitespace()
                .map(|t| t.parse::<$t>().unwrap())
                .collect::<Vec<_>>()
        }
    };
}

#[allow(unused_macros)]
macro_rules! debug {
    ($($a:expr),*) => {
        println!(concat!($(stringify!($a), " = {:?}, "),*), $($a),*);
    }
}

fn main() {
    let (k, p) = get!(usize, u64);

    let mut sum = 0;
    for i in 1..k + 1 {
        let mut v = Vec::new();
        let mut x = i as u64;
        while x > 0 {
            v.push(x % 10);
            x /= 10;
        }

        let l = v.len() * 2;
        for (i, &x) in v.iter().rev().enumerate() {
            sum += 10u64.pow(i as u32) * x;
            sum %= p;
            sum += 10u64.pow((l - i - 1) as u32) * x;
            sum %= p;
        }

    }

    println!("{}", sum);
}


#![allow(non_snake_case, unused_imports, deprecated, dead_code)]

// Input macros
macro_rules! input { (source = $s:expr, $($r:tt)*) => { let mut iter = $s.split_whitespace(); let mut next = || { iter.next().unwrap() }; input_inner!{next, $($r)*} }; ($($r:tt)*) => { let stdin = std::io::stdin(); let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock())); let mut next = move || -> String{ bytes.by_ref().map(|r|r.unwrap() as char).skip_while(|c|c.is_whitespace()).take_while(|c|!c.is_whitespace()).collect() }; input_inner!{next, $($r)*} }; }
macro_rules! input_inner { ($next:expr) => {}; ($next:expr, ) => {}; ($next:expr, $var:ident : $t:tt $($r:tt)*) => { let $var = read_value!($next, $t); input_inner!{$next $($r)*} }; ($next:expr, mut $var:ident : $t:tt $($r:tt)*) => { let mut $var = read_value!($next, $t); input_inner!{$next $($r)*} }; }
macro_rules! read_value { ($next:expr, ( $($t:tt),* )) => { ( $(read_value!($next, $t)),* ) }; ($next:expr, [ $t:tt ; $len:expr ]) => { (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>() }; ($next:expr, [ $t:tt ]) => { { let len = read_value!($next, usize); (0..len).map(|_| read_value!($next, $t)).collect::<Vec<_>>() } }; ($next:expr, chars) => { read_value!($next, String).chars().collect::<Vec<char>>() }; ($next:expr, bytes) => { read_value!($next, String).into_bytes() }; ($next:expr, usize1) => { read_value!($next, usize) - 1 }; ($next:expr, $t:ty) => { $next().parse::<$t>().expect("Parse error") }; }

// Module
use std::cmp::{min,max};
use std::collections::{VecDeque,HashSet,HashMap,BinaryHeap};
// Module for v1.15.1
use std::ascii::AsciiExt; // deprecated since 1.26.0: use inherent method instead

// Functions

// Main
fn main() {

    input! {
        N: chars,
    }

    let mut ans = "YES";
    let mut cnt_4 = 0;

    // 最上位は 1 必須
    if N[0] != '1' {
        ans = "NO";
    } else {
        for i in 1..N.len() {
            if N[i] == '1' {
                cnt_4 = 0;
                continue;
            // 4 は連続2回まで
            } else if N[i] == '4' {
                cnt_4 += 1;
                if cnt_4 > 2 {
                    ans = "NO";
                    break;
                }
            } else {
                ans = "NO";
                break;
            }
        }
    }
    println!("{}", ans);
}


struct Scan {
    buffer: std::collections::VecDeque<String>,
}

impl Scan {
    fn new() -> Scan {
        Scan {
            buffer: std::collections::VecDeque::new(),
        }
    }

    fn next<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop_front() {
                break token.parse::<T>().ok().unwrap();
            }
            let mut line = String::new();
            std::io::stdin().read_line(&mut line).expect("Fail to read");
            self.buffer = line.split_whitespace().map(String::from).collect();
        }
    }
}

fn _main() {
    let mut scan = Scan::new();
    let mut input: usize = scan.next();
    let mut result = true;
    let mut count4 = 0usize;
    let mut digit = 0usize;
    while input > 0 {
        digit = input % 10;
        input /= 10;
        if digit == 4 {
            count4 += 1;
            if count4 > 2 {
                result = false;
                break;
            }
        } else if digit == 1 {
            count4 = 0;
        } else {
            result = false;
            break;
        }
    }
    println!("{}", if result && digit != 4 { "YES" } else { "NO" });
}

fn main() {
    std::thread::Builder::new()
        .stack_size(1 << 23)
        .spawn(_main)
        .unwrap()
        .join()
        .unwrap();
}


#[allow(unused_imports)]
use std::cmp::{min,max};
use std::collections::{*};
use std::io::{BufWriter, stdin, stdout, Write};
const BITS: usize = 19;

#[derive(Default)]
struct Scanner {
    buffer: Vec<String>
}
impl Scanner {
    fn next<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();
            stdin().read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
}

fn main() {
    let mut scanner = Scanner::default();
    let dx: [i32;3] = [1, 0, -1];
    let mut arr: [[u64;3];3] = [[0;3];3];
    for i in 0..3 {
    	for j in 0..3{
    		let times: u64 = scanner.next();
    		for x in &dx {
    			for y in &dx {
    				if i + *x < 3 && j + *y < 3 && i + *x > -1 && j + *y > -1 && (*x).abs() + (*y).abs() <= 1{
    					arr[(i + *x) as usize][(j + *y) as usize] += times;
    				}
    			}
    		}
    	}
    }
    for i in 0usize..3{
    	for j in 0usize..3{
    		if arr[i][j]%2 == 1 {
    			print!["0"];
    		} else {
    			print!["1"];
    		}
    	}
    	println![""];
    }
}


use std::io;
use std::io::BufRead;

type Grid = Vec<Vec<usize>>;

fn valid_index(index: isize) -> bool {
    index >= 0 && index <= 2
}

fn get_position(grid: &Grid, x: isize, y: isize) -> usize {
    if !valid_index(x) || !valid_index(y) {
        0
    } else {
        *grid.get(y as usize).and_then(|n| n.get(x as usize).or(Some(&0))).unwrap_or(&0)
    }
}

fn main() {
    let numbers: Grid = io::stdin()
        .lock()
        .lines()
        .take(3)
        .map(|line| line.expect("failed to read line")
                .trim()
                .split(" ")
                .map(|number| number.parse::<usize>().expect("failed to parse number"))
                .collect()
            )
        .collect();

    for y in 0 as isize..3 {
        for x in 0 as isize..3 {
            let mut n = get_position(&numbers, x, y);
            n += get_position(&numbers, x, y - 1);
            n += get_position(&numbers, x, y + 1);
            n += get_position(&numbers, x - 1, y);
            n += get_position(&numbers, x + 1, y);
            print!("{}", match n % 2 {
                0 => 1,
                1 => 0,
                _ => unreachable!()
            });
        }
        println!("");
    }
}


use std::io::{BufReader, BufRead};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut distance = BufReader::new(std::io::stdin())
        .lines()
        .map(Result::unwrap)
        .next()
        .unwrap()
        .parse::<usize>()?;

    let mut steps = 0;
    for step in &[5, 4, 3, 2, 1] {
        if distance == 0 { break }
        steps += distance / step;
        distance %= step;
    }

    println!("{}", steps);
    Ok(())
}


// {{{ by shik

use std::io;

#[allow(dead_code)]
fn gets() -> String {
    let mut s = String::new();
    io::stdin().read_line(&mut s).unwrap();
    s.trim().to_string()
}

#[allow(unused_macros)]
macro_rules! R {
    ( $ty:ty, ... ) => {
        gets().split_whitespace().map(|x| x.parse::<$ty>().unwrap()).collect::<Vec<_>>()
    };
    ( $($ty:ty),* ) => {{
        let line = gets();
        let mut it = line.split_whitespace();
        ( $(it.next().unwrap().parse::<$ty>().unwrap(),)* )
    }}
}

#[allow(unused_macros)]
macro_rules! W {
    ( $x:expr ) => {{
        println!("{}", $x);
    }};
    ( $x:expr, $($xs:expr),* ) => {{
        print!("{} ", $x);
        W!($($xs),*);
    }}
}

#[allow(unused_macros)]
macro_rules! join {
    ($x:expr, $($xs:expr),*; $sep:expr) => { concat!($x, $($sep, $xs),*) }
}

#[allow(unused_macros)]
macro_rules! dump {
    ($($x:expr),*) => {
        eprintln!(join!($(concat!(stringify!($x), " = {:?}")),*; ", "), $($x),*);
    }
}

// }}}

fn main() {
    let (n, ) = R!(usize);
    println!("{}", n/5 + (if n % 5 != 0 { 1 } else { 0 }));
}


use std::io::stdin;

fn main() {
    let mut buf = String::new();
    let _ = stdin().read_line(&mut buf);
    let mut x = buf.trim_end().parse::<i32>().unwrap();
    let mut ans = 0;
    let mut iter = 5;
    while iter > 0 && x >= 0 {
        ans += x / iter;
        x -= iter * (x / iter);
        iter -= 1;
    }
    println!("{}\n", ans);
}


use std::io;

fn main() {
    let mut input = String::new();
        io::stdin().read_line(&mut input).expect("Failed to read line");

        let input: u32   = input.trim().parse().expect("Please Type a number!");

        if input%5 == 0{
            println!("{}",input/5);
        }
        else{
            println!("{}",input/5+1)
        }
    }


fn main() {
    let mut text = String::new();
    std::io::stdin().read_line(&mut text).expect("");
    println!("{}", resolver(text.trim().parse().expect("msg: &str"), 0));
}

fn resolver(value: usize, step: usize) -> usize {
    if value > 5 {
        resolver(value % 5, value / 5)
    } else {
        if value == 1 {
            step + 1
        } else if value % 5 == 0 {
            (value / 5) + step
        } else if value % 4 == 0 {
            (value / 4) + step
        } else if value % 3 == 0 {
            (value / 3) + step
        } else {
            (value / 2) + step
        }
    }
}


use std::io;

fn main() {
    let mut val = String::new();

    io::stdin().read_line(&mut val)
        .expect("Не удалось прочитать строку");

    let val: i32 = val.trim().parse()
        .expect("Пожалуйста, введите число!");

    let ans = val / 5;
    println!("{}", ans + (val % 5 > 0) as i32);
}


fn get_input() -> String {
	let mut buffer = String::new();
	std::io::stdin().read_line(&mut buffer).expect("Failed");
	buffer
}

fn main() {
	let x = get_input().trim().parse::<i32>().unwrap();

	let mut cnt = x / 5;
	let dv = x % 5;

	if dv != 0 {
		cnt += 1;
	}

	print!("{}", cnt);
}


#![allow(unused_imports)]
use std::io::*;
use std::cmp::*;
use std::collections::*;

macro_rules! debug(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

struct Scanner {
   buffer : std::collections::VecDeque<String>
}

impl Scanner {

   fn new() -> Scanner {
      Scanner {
         buffer: std::collections::VecDeque::new()
      }
   }

   fn process(&mut self) -> String {
      if self.buffer.len() == 0 {
         let mut input = String::new();
         std::io::stdin().read_line(&mut input).ok();
         for word in input.split_whitespace() {
            self.buffer.push_back(word.to_string())
         }
      }

      self.buffer.pop_front().unwrap()
   }

   #[allow(dead_code)]
   fn next<T : std::str::FromStr >(&mut self) -> T {
      self.process().parse::<T>().ok().unwrap()
   }

   #[allow(dead_code)]
   fn next_char(&mut self) -> char {
      self.process().into_bytes()[0] as char
   }
}

fn main() {
    let mut sin = Scanner::new();
    let n = sin.next::<i32>();

    let result = n / 5 + (0 != n % 5) as i32;
    println!("{}", result);
}


#[allow(unused_imports)]
use std::cmp::{max,min};
#[allow(unused_imports)]
use std::collections::{HashMap,HashSet,VecDeque};

#[allow(unused_macros)]
macro_rules! readln {
    () => {{
        use std::io;

        let mut buf = String::new();
        io::stdin().read_line(&mut buf).unwrap();
        buf.trim().to_string()
    }};
    ( $t:ty ) => {{
        let input = readln!();
        input.parse::<$t>().unwrap()
    }};
    ( $( $t:ty ),+ ) => {{
        let input = readln!();
        let mut input = input.split_whitespace();
        (
            $(
                input.next().unwrap().parse::<$t>().unwrap(),
            )+
        )
    }}
}

#[allow(unused_macros)]
macro_rules! readvec {
    ( $t:ty ) => {{
        let input = readln!();
        let mut input = input.split_whitespace();
        let mut result = Vec::new();
        for elem in input {
            result.push(elem.parse::<$t>().unwrap());
        }
        result
    }}
}

fn main() {
  let ss = readln!();
  let s = ss.as_bytes();
  let n = s.len();
  let mut need = 0;
  for i in 0..(n/2) {
    if s[i] != s[n-1-i] {
      need += 1;
    }
  }
  if need == 1 || (need == 0 && (n%2) == 1) {
    println!("YES");
  } else {
    println!("NO");
  }
}


use std::io;
use std::io::{Error, ErrorKind};
use std::str::FromStr;

struct IO {
    buffer: Vec<String>
}

impl IO {
    fn new() -> IO {
        IO { buffer: Vec::new() }
    }
    /*
    pub fn reset(&mut self) {
        self.buffer = Vec::new();
    }
    */

    fn try_parse<T>(s: String) -> Result<T, T::Err>
        where T: FromStr {
        let res = (&s).parse::<T>()?;
        Ok(res)
    }

    fn receive<T>(&mut self) -> Result<T, Error>
        where T: FromStr {
        let ref mut stdio = &mut io::stdin();
        if let Some(s) = self.buffer.pop() {
            return match IO::try_parse::<T>(s) {
                Ok(value) => Ok(value),
                _ => Err(Error::new(ErrorKind::Other, "cannot parse to desired type"))
            }
        }

        let mut input = String::new();
        if let Err(error) = stdio.read_line(&mut input) {
            return Err(error)
        }

        input = input.trim().to_string();

        self.buffer.extend::<Vec<String> >(input.split(' ').map(|s| s.to_string()).collect());

        return self.receive::<T>()
    }
}

fn main() {
    let mut sio = IO::new();
    let s = sio.receive::<String>().unwrap();
    let q = s.bytes().collect::<Vec<u8> >();
    let mut diff = 0;
    for i in 0..s.len() {
        if q[i] != q[s.len() - 1 - i] {
            diff += 1;
        }
    }
    if diff == 2 || (diff == 0 && s.len() % 2 == 1){
        println!("YES");
    } else {
        println!("NO");
    }
}


//spnauti-rust
use std::io::*;
use std::str::*;
use std::fmt::Debug;
#[allow(unused_imports)] use std::cmp::Ordering::*;
#[allow(unused_imports)] use std::collections::*;

#[allow(unused_macros)]
macro_rules! a {
    ($c: tt, $x: expr, $y: expr) => {{
        let b = $y; let a = &mut $x;
        if b $c *a { *a = b; true } else { false }
    }};
}
struct WordReader<'a> { it : SplitAsciiWhitespace<'a>, }
#[allow(dead_code)]
impl<'a> WordReader<'a> {
    fn new<T: Read>(b: &mut String, mut r: T) -> WordReader {
        b.clear();
        r.read_to_string(b).unwrap();
        WordReader { it: b.split_ascii_whitespace() }
    }
    fn from_stdin(b: &mut String) -> WordReader {
        WordReader::new(b, stdin())
    }
    fn sl(&mut self) ->  &str { self.it.next().unwrap() }
    fn bs(&mut self) -> &[u8] { self.sl().as_bytes()    }
    fn s(&mut self) -> String { String::from(self.sl()) }
    fn i(&mut self) ->    i32 { self.p()                }
    fn u(&mut self) ->  usize { self.p()                }
    fn vi(&mut self, n: usize) -> Vec<i32> {
        self.vp::<i32>(n)
    }
    fn p<T: FromStr>(&mut self) -> T where T::Err: Debug {
        self.sl().parse::<T>().unwrap()
    }
    fn vp<T: FromStr>(&mut self, n: usize) -> Vec<T> where T::Err: Debug {
        (0..n).map(|_| self.p()).collect()
    }
}

#[allow(dead_code)]
fn build_counting_hashmap<K: Eq + std::hash::Hash, T>(i: T) -> HashMap<K,usize>
    where T: Iterator<Item = K> {
    let mut m = HashMap::new();
    for k in i {
        let n = 1 + if let Some(&n) = m.get(&k) { n } else { 0 };
        m.insert(k, n);
    }
    m
}

fn main() {
    let mut bin = String::new();
    let mut input = WordReader::from_stdin(&mut bin);

    let s = input.bs();
    let n = s.len();
    let x = (0..n).zip((0..n).rev()).filter(|(a,b)| a < b && s[*a] != s[*b]).count();
    if (n % 2 == 1 && x <= 1) || (n % 2 == 0 && x == 1) {
        println!("YES");
    } else {
        println!("NO");
    }
}


#![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


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


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


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


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


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


fn main() {
    let friend_count = get_input_usize();
    let finger_count: usize = get_input().split_ascii_whitespace().map(|v| v.parse::<usize>().unwrap()).sum();

    let total_people = friend_count + 1;
    let position = finger_count % total_people;

    let res = vec![1,2,3,4,5].iter().fold(0, |res, next| {
        if (next + position) % total_people == 1 {
            res
        } else {
            res + 1
        }
    });

    println!("{}", res);

}

fn get_input() -> String {
    let mut buffer = String::new();
    std::io::stdin().read_line(&mut buffer).expect("Failed");
    buffer.trim().to_owned()
}

fn get_input_usize() -> usize {
    get_input().parse().unwrap()
}


fn read_int() -> u16 {
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).expect("Failed");
    let x = input.trim().parse::<u16>().unwrap();
    x
}

fn read_int_vec() -> Vec<u16>{
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).expect("rFailed");
    let vec = input.split_whitespace()
        .map(|i| i.parse::<u16>().expect("parse error"))
        .collect::<Vec<u16>>();
    vec
}

fn main() {

    let x = read_int() + 1;
    let vec = read_int_vec();
    let sum: u16 = vec.iter().sum();

    let mut total = 0;
    let mut range = 1..6;
    loop {
        match range.next() {
            Some(i) => {
                // println!("also: ({}+{}) % {} = {}", sum, i, x, (((sum+i) % x) + x)% x);
                if !((((sum+i) % x) + x) % x == 1){
                    // println!("====");
                    total = total + 1;
                }
            },
            None => { break }
        }
    }
    println!("{}", total);

}


use std::io;
use std::str::FromStr;

fn get_num() -> i32 {
    let mut input = String::new();

    io::stdin().read_line(&mut input)
        .expect("");

    i32::from_str(input.trim()).unwrap()
}

fn get_nums() -> Vec<i32> {
    let mut input = String::new();

    io::stdin().read_line(&mut input)
        .expect("");

    input.trim()
        .split_whitespace()
        .map(|s| i32::from_str(s).unwrap())
        .collect::<Vec<_>>()
}

fn main() {
    let n = get_num();
    let s = get_nums().iter().sum::<i32>();

    let mut c = 0;
    for i in 1..=5 {
        if (s + i - n - 2) % (n + 1) != 0 {
            c += 1;
        }
    }

   println!("{}", c);
}


#[allow(unused_imports)]
use std::cmp::{min,max};
use std::collections::{*};
use std::io::{BufWriter, stdin, stdout, Write};
const BITS: usize = 19;

#[derive(Default)]
struct Scanner {
    buffer: Vec<String>
}
impl Scanner {
    fn next<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();
            stdin().read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
}

fn main() {
    let mut scanner = Scanner::default();
    let n: u128 = scanner.next();
    let sum = (1..=n).fold(0u128, |acc, x| acc + scanner.next::<u128>());
    println!["{:?}", (1..=5).map(|x| sum + x).filter(|x| x % (n+1) != 1).count()];
}


fn main() {
    let mut input = String::new();
    use std::io;
    use std::io::prelude::*;
    io::stdin().read_to_string(&mut input).unwrap();

    let n: u64 = input.trim().parse().unwrap();

    let ans = n / 2 + 1;

    println!("{}", ans)
}


use std::io;
use std::io::Stdin;
use std::str::FromStr;

fn read_line(stdin : &Stdin, line : &mut String) {
    match stdin.read_line(line) {
        Ok(_) => return,
        Err(msg) => panic!("Could not read line! Message: {}.", msg),
    }
}

fn parse_t<T : FromStr>(s : &str) -> T {
    match s.trim().parse() {
        Ok(y) => y,
        Err(_) => panic!("Could not read from string!"),
    }
}

fn read_t<T : FromStr>(stdin : &Stdin) -> T {
    let mut line = String::new();
    read_line(stdin, &mut line);
    parse_t(&line)
}

fn main() {
    let stdin = io::stdin();
    let n : u64 = read_t(&stdin);
    let s = (n / 2) + 1;
    println!("{}", s);
}