#[allow(unused_imports)] use std::cmp::{min,max}; #[allow(unused_imports)] use std::collections::BTreeMap; #[allow(unused_imports)] use std::ops::*; #[allow(unused_imports)] use std::collections::BinaryHeap; #[allow(unused_macros)] macro_rules! tf { ($c:expr, $t:expr, $f:expr) => {{ if $c { $t } else { $f } }}; } fn main() { let n = read_i64(); let mut res = Mod(1); for i in 2..n+1 { res = res * Mod(i as u64) * Mod(((2*i) * (2*i-1) / 2) as u64); } println!("{}", res.0); } const MOD : u64 = 1_000_000_007; #[derive(Clone,Copy,PartialEq)] struct Mod (u64); use std::ops::*; impl Mod { fn pow(self, n: u64) -> Mod { if n == 0 { return Mod(1); } let t = self.pow(n/2); if n % 2 == 0 { t * t } else { t * t * self } } } impl Add for Mod { type Output = Self; fn add(self, rhs: Self) -> Self::Output { Mod((self.0 + rhs.0) % MOD) } } impl AddAssign for Mod { fn add_assign(&mut self, rhs: Self) { *self = *self + rhs; } } impl Sub for Mod { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { Mod((self.0 + MOD - rhs.0 % MOD) % MOD) } } impl SubAssign for Mod { fn sub_assign(&mut self, rhs: Self) { *self = *self - rhs; } } impl Mul for Mod { type Output = Self; fn mul(self, rhs: Self) -> Self::Output { Mod(self.0 % MOD * rhs.0 % MOD) } } impl Div for Mod { type Output = Self; fn div(self, rhs: Self) -> Self::Output { self * rhs.pow(MOD-2) } } #[allow(dead_code)] fn read_line() -> String { let mut ret = String::new(); std::io::stdin().read_line(&mut ret).ok(); ret.pop(); return ret; } #[allow(dead_code)] fn read_i64() -> i64 { let ss = read_line(); return ss.parse::().unwrap(); } #[allow(dead_code)] fn read_vec_i64() -> Vec { let mut res = vec![]; let ss = read_line(); for ts in ss.split_whitespace() { let x = ts.parse::().unwrap(); res.push(x); } return res; } use std::fmt::Display; #[allow(dead_code)] fn write_vec(xs: &Vec) { if xs.len() == 0 { println!(""); return; } print!("{}", xs[0]); for i in 1..xs.len() { print!(" {}", xs[i]); } println!(""); }