#![allow(non_snake_case)] use crate::{combinations::array::Comb, scanner::Scanner}; modint!(); fn main() { let mut scan = Scanner::new(); let n = scan.int(); let m = scan.int(); let d1 = scan.int(); let d2 = scan.int(); let comb = Comb::::new(n + m + 100); let mut ret = Z::zero(); for i in 0..=n - 1 { ret += comb.of(n - 1, i) * if i & 1 == 0 { Z::one() } else { Z::new(-1) } * comb.rep(n + 1, m - 1 - d1 * (n - 1) - i * (d2 - d1 + 1)); } println!("{}", ret); } pub mod modulo { use crate::nums::inv_gcd; use crate::{impl_integer_functions, independent::integer::Int}; use std::cell::RefCell; use std::fmt::Debug; use std::marker::PhantomData; use std::ops::*; use std::sync::atomic::{self, AtomicU32}; use std::thread::LocalKey; pub trait Modulus: 'static + PartialEq + Eq + Copy + Clone + std::hash::Hash + Ord { const M: u32; const HINT_M_IS_PRIME: bool; fn butterfly_cache() -> &'static LocalKey>>>; } pub trait DynamicModulus: 'static + PartialEq + Eq + Copy + Clone + std::hash::Hash + Ord { fn state() -> &'static AtomicU32 { static M: AtomicU32 = AtomicU32::new(1_000_000_007); &M } fn update(m: u32) { Self::state().store(m, atomic::Ordering::SeqCst) } fn umod() -> u32 { Self::state().load(atomic::Ordering::SeqCst) } } #[derive(PartialEq, Eq, Copy, Clone, Hash, PartialOrd, Ord)] pub enum DefaultId {} impl DynamicModulus for DefaultId {} macro_rules! impl_from_for_modint { ($name:ident, $guard: ident, $($tpe:ident),*) => { $( impl From<$tpe> for $name { fn from(n: $tpe) -> Self { Self::new(n) } } )* }; } macro_rules! impl_assign { ($name:ident, $guard:ident, $($t1:ty, $t2:ty, $fa:ident, $f:ident),*) => { $( impl $t1 for $name { type Output = Self; #[inline] fn $f(self, other: Self) -> Self { ::$f(self, other) } } impl $t2 for $name { #[inline] fn $fa(&mut self, other: Self) { *self = ::$f(*self, other); } } )* }; } macro_rules! impl_modint_structs { ($name:ident, $guard:ident) => { #[derive(PartialEq, Eq, Copy, Clone, Hash, PartialOrd, Ord)] #[repr(transparent)] pub struct $name { pub val: u32, phantom: PhantomData T>, } impl Debug for $name { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.val.fmt(f) } } impl $name { #[inline] pub fn new(a: U) -> Self { ::new(a) } #[inline] pub fn inv(self) -> Self { ::inv(self) } #[inline] pub fn raw(val: u32) -> Self { Self { val, phantom: PhantomData, } } #[inline] pub fn pow(self, x: U) -> Self { ::pow(self, x) } #[inline] pub fn zero() -> Self { ::zero() } #[inline] pub fn one() -> Self { ::one() } } impl std::fmt::Display for $name { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", self.val) } } impl_from_for_modint!( $name, $guard, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize ); impl_assign!( $name, $guard, Add, AddAssign, add_assign, add, Sub, SubAssign, sub_assign, sub, Mul, MulAssign, mul_assign, mul, Div, DivAssign, div_assign, div, Rem, RemAssign, rem_assign, rem ); impl Int for $name { impl_integer_functions!(|s: &Self| s.val, |x| Self::new(x), |s: &Self, n: i64| s .pow(n)); } }; } impl_modint_structs!(StaticModInt, Modulus); impl_modint_structs!(DynamicModInt, DynamicModulus); #[macro_export] macro_rules! modint { () => {$crate::modint!(1000000007, true);}; ($m:literal) => {$crate::modint!($m, true);}; ($m:literal, $is_prime:literal) => { $crate::modint!($m, ModValue, $is_prime); #[allow(dead_code)] type Z = $crate::modulo::StaticModInt; }; ($name:ident) => { $crate::modint!($name, $name, true); }; ($value:expr, $name:ident, $is_prime:literal) => { #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, PartialOrd, Ord)] pub enum $name {} impl $crate::modulo::Modulus for $name { const M: u32 = $value as _; const HINT_M_IS_PRIME: bool = $is_prime; fn butterfly_cache() -> &'static ::std::thread::LocalKey<::std::cell::RefCell<::std::option::Option<$crate::modulo::ButterflyCache>>> { thread_local! { static BUTTERFLY_CACHE: ::std::cell::RefCell<::std::option::Option<$crate::modulo::ButterflyCache<$name>>> = ::std::default::Default::default(); } &BUTTERFLY_CACHE } } }; } pub type D = DynamicModInt; pub trait ModInt: Int { fn new(val: U) -> Self { let x = val.to_i128(); Self::raw(x.rem_euclid(Self::modulus() as i128) as _) } fn inv(self) -> Self { if Self::mod_is_prime() { Self::pow(self, Self::modulus() - 2) } else { let (g, x) = inv_gcd(Self::val(self) as _, Self::modulus() as _); if g != 1 { panic!("the multiplicative inverse does not exist"); } else { Self::new(x) } } } fn raw(val: u32) -> Self; fn val(self) -> u32; fn modulus() -> u32; fn mod_is_prime() -> bool; fn add(self, other: Self) -> Self { let mut ret = self.val() + other.val(); if ret >= Self::modulus() { ret -= Self::modulus(); } Self::raw(ret) } fn sub(self, other: Self) -> Self { let mut ret = self.val().wrapping_sub(other.val()); if ret >= Self::modulus() { ret = ret.wrapping_add(Self::modulus()); } Self::raw(ret) } fn mul(self, other: Self) -> Self { Self::raw( (u64::from(self.val()) * u64::from(other.val()) % u64::from(Self::modulus())) as _, ) } fn div(self, other: Self) -> Self { self * other.inv() } fn rem(self, other: Self) -> Self { Self::raw(self.val() % other.val()) } fn pow(self, x: U) -> Self { let mut n = x.to_i64(); let mut a = self; let mut res = Self::raw(1); while n > 0 { if n & 1 == 1 { res *= a; } a = a * a; n >>= 1; } res } } impl ModInt for StaticModInt { fn raw(val: u32) -> Self { Self::raw(val) } fn val(self) -> u32 { self.val } fn modulus() -> u32 { M::M } fn mod_is_prime() -> bool { M::HINT_M_IS_PRIME } } impl ModInt for DynamicModInt { fn raw(val: u32) -> Self { Self::raw(val) } fn val(self) -> u32 { self.val } fn modulus() -> u32 { M::umod() } fn mod_is_prime() -> bool { false } } pub struct ButterflyCache { pub sum_e: Vec>, pub sum_ie: Vec>, } } pub mod arraylist { use std::ops::*; use std::slice::Iter; use std::fmt::Formatter; use std::iter::FromIterator; #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct List { pub data: Vec, } impl List { #[inline] pub fn init(init: T, n: isize) -> List where T: Clone, { List { data: vec![init; n as usize], } } } macro_rules! impl_idx { ($($tpe:ty, $t:ident [$($output:tt)+], $slf:ident, $index:ident, $f:expr),*) => { $(impl<$t> Index<$tpe> for List<$t> { type Output = $($output)+; #[inline] fn index(&$slf, $index: $tpe) -> &Self::Output {$f} })* $(impl<$t> Index<$tpe> for lst<$t> { type Output = $($output)+; #[inline] fn index(&$slf, $index: $tpe) -> &Self::Output {$f} })* } } macro_rules! impl_idx_mut { ($($tpe:ty, $slf:ident, $index:ident, $f:expr),*) => { $(impl IndexMut<$tpe> for List { #[inline] fn index_mut(&mut $slf, $index: $tpe) -> &mut Self::Output {$f} })* $(impl IndexMut<$tpe> for lst { #[inline] fn index_mut(&mut $slf, $index: $tpe) -> &mut Self::Output {$f} })* }; } macro_rules! impl_idx_slice { ($($tpe:ty),*) => { impl_idx!($($tpe, T [lst], self, i, self.as_slice(i)),*); impl_idx_mut!($($tpe, self, i, self.as_slice_mut(i)),*); }; } impl_idx! { isize, T [T], self, i, self.at(i), char, T [T], self, i, self.at(i as isize - 'a' as isize) } impl_idx_slice! { Range, RangeTo, RangeFrom, RangeFull, RangeInclusive, RangeToInclusive } impl_idx_mut! { isize, self, i, self.at_mut(i), char, self, i, self.at_mut(i as isize - 'a' as isize) } impl FromIterator for List { #[inline] fn from_iter>(iter: U) -> Self { List { data: iter.into_iter().collect(), } } } impl IntoIterator for List { type Item = T; type IntoIter = std::vec::IntoIter; #[inline] fn into_iter(self) -> std::vec::IntoIter { self.data.into_iter() } } macro_rules! impl_traits { ($($tpe:tt),*) => { $( impl std::fmt::Display for $tpe { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", self.iter().map(|x| format!("{}", x)).collect::>().join(" ")) } } impl std::fmt::Debug for $tpe { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { self.data.fmt(f) } } impl<'a, T> IntoIterator for &'a $tpe { type Item = &'a T; type IntoIter = Iter<'a, T>; #[inline] fn into_iter(self) -> Iter<'a, T> { self.iter() } } )* }; } impl_traits!(List, lst); impl From> for List { #[inline] fn from(vec: Vec) -> Self { List { data: vec } } } impl From<&[T]> for List { #[inline] fn from(slice: &[T]) -> Self { slice.iter().cloned().collect() } } impl Deref for List { type Target = lst; #[inline] fn deref(&self) -> &lst { lst::new(&self.data) } } impl DerefMut for List { #[inline] fn deref_mut(&mut self) -> &mut lst { lst::new_mut(&mut self.data) } } #[macro_export] macro_rules! list { () => { $crate::arraylist::List::new() }; ($($v:expr),+ $(,)?) => { $crate::arraylist::List::from([$($v),+].to_vec()) }; ($v:expr; $a:expr) => { $crate::arraylist::List::init($v, $a)}; ($v:expr; $a:expr; $($rest:expr);+) => { $crate::arraylist::List::init(list!($v; $($rest);+), $a) }; } #[allow(non_camel_case_types)] #[derive(PartialEq, Eq, PartialOrd, Ord)] #[repr(transparent)] pub struct lst { data: [T], } impl lst { #[inline] pub fn new(slice: &[T]) -> &Self { unsafe { &*(slice as *const [T] as *const Self) } } #[inline] pub fn new_mut(slice: &mut [T]) -> &mut Self { unsafe { &mut *(slice as *mut [T] as *mut Self) } } #[inline] fn at(&self, index: isize) -> &T { if cfg!(debug_assertions) { self.data.index(index as usize) } else { unsafe { self.data.get_unchecked(index as usize) } } } #[inline] fn at_mut(&mut self, index: isize) -> &mut T { if cfg!(debug_assertions) { self.data.index_mut(index as usize) } else { unsafe { self.data.get_unchecked_mut(index as usize) } } } #[inline] pub fn as_slice(&self, range: impl RangeBounds) -> &lst { if cfg!(debug_assertions) { lst::new(self.data.index(self.rgm(range))) } else { unsafe { lst::new(self.data.get_unchecked(self.rgm(range))) } } } #[inline] pub fn as_slice_mut(&mut self, range: impl RangeBounds) -> &mut lst { if cfg!(debug_assertions) { lst::new_mut(self.data.index_mut(self.rgm(range))) } else { let r = self.rgm(range); unsafe { lst::new_mut(self.data.get_unchecked_mut(r)) } } } #[inline] fn rgm(&self, r: impl RangeBounds) -> Range { (match r.start_bound() { Bound::Included(x) => *x as usize, Bound::Excluded(x) => *x as usize + 1, _ => 0, }) .max(0)..(match r.end_bound() { Bound::Included(x) => *x as usize + 1, Bound::Excluded(x) => *x as usize, _ => self.len(), }) .min(self.len()) } } impl lst {} impl Deref for lst { type Target = [T]; #[inline] fn deref(&self) -> &[T] { &self.data } } impl DerefMut for lst { #[inline] fn deref_mut(&mut self) -> &mut [T] { &mut self.data } } impl<'a, T> From<&'a [T]> for &'a lst { #[inline] fn from(slice: &'a [T]) -> Self { lst::new(slice) } } } pub mod combinations { pub mod array { use crate::{arraylist::List, modulo::ModInt}; pub struct Comb { fact: List, ifact: List, } impl Comb { pub fn new(n: isize) -> Self { let mut fact = List::init(T::zero(), n + 1); let mut ifact = List::init(T::zero(), n + 1); fact[0] = T::one(); for i in 1..=n { fact[i] = fact[i - 1] * T::from_isize(i); } ifact[n] = fact[n].inv(); for i in (1..=n).rev() { ifact[i - 1] = ifact[i] * T::from_isize(i); } Comb { fact, ifact } } pub fn of(&self, n: isize, k: isize) -> T { if n < k || n < 0 || k < 0 { T::zero() } else { self.fact[n] * self.ifact[k] * self.ifact[n - k] } } pub fn rep(&self, n: isize, k: isize) -> T { self.of(n + k - 1, k) } } } } pub mod scanner { use std::io::{stdin, BufReader, Bytes, Read, Stdin}; use std::str::FromStr; pub struct Scanner { buf: Bytes>, } impl Scanner { pub fn new() -> Scanner { Scanner { buf: BufReader::new(stdin()).bytes(), } } #[inline] fn token>(&mut self) -> T { self.buf .by_ref() .map(|c| c.unwrap() as char) .skip_while(|c| c.is_whitespace()) .take_while(|c| !c.is_whitespace()) .collect() } #[inline] pub fn read(&mut self) -> T { self.string().parse().ok().unwrap() } #[inline] pub fn string(&mut self) -> String { self.token() } #[inline] pub fn int(&mut self) -> isize { self.read() } } } pub mod nums { use std::mem::swap; pub fn inv_gcd(a: i64, b: i64) -> (i64, i64) { let a = a.rem_euclid(b); if a == 0 { return (b, 0); } let mut s = b; let mut t = a; let mut m0 = 0; let mut m1 = 1; while t != 0 { let u = s / t; s -= t * u; m0 -= m1 * u; swap(&mut s, &mut t); swap(&mut m0, &mut m1); } if m0 < 0 { m0 += b / s; } (s, m0) } } pub mod independent { pub mod integer { use std::fmt::Display; use std::ops::*; pub trait Int: Add + Sub + Mul + Div + Rem + AddAssign + SubAssign + MulAssign + DivAssign + RemAssign + std::hash::Hash + PartialEq + Eq + PartialOrd + Ord + Copy + Display { fn to_u8(&self) -> u8; fn to_u16(&self) -> u16; fn to_u32(&self) -> u32; fn to_u64(&self) -> u64; fn to_u128(&self) -> u128; fn to_i8(&self) -> i8; fn to_i16(&self) -> i16; fn to_i32(&self) -> i32; fn to_i64(&self) -> i64; fn to_i128(&self) -> i128; fn to_usize(&self) -> usize; fn to_isize(&self) -> isize; fn from_u8(x: u8) -> Self; fn from_u16(x: u16) -> Self; fn from_u32(x: u32) -> Self; fn from_u64(x: u64) -> Self; fn from_u128(x: u128) -> Self; fn from_i8(x: i8) -> Self; fn from_i16(x: i16) -> Self; fn from_i32(x: i32) -> Self; fn from_i64(x: i64) -> Self; fn from_i128(x: i128) -> Self; fn from_usize(x: usize) -> Self; fn from_isize(x: isize) -> Self; fn zero() -> Self; fn one() -> Self; fn next(&self) -> Self { *self + Self::one() } fn powint(&self, n: i64) -> Self; } #[macro_export] macro_rules! impl_integer_functions { ($to_op:expr, $from_op:expr, $pow:expr) => { impl_integer_functions!( $to_op, $from_op, $pow, to_u8, from_u8, u8, to_u16, from_u16, u16, to_u32, from_u32, u32, to_u64, from_u64, u64, to_u128, from_u128, u128, to_i8, from_i8, i8, to_i16, from_i16, i16, to_i32, from_i32, i32, to_i64, from_i64, i64, to_i128, from_i128, i128, to_usize, from_usize, usize, to_isize, from_isize, isize ); }; ($to_op:expr, $from_op:expr, $pow:expr, $($tofn:ident, $fromfn:ident, $tpe:ident),*) => { $( fn $tofn(&self) -> $tpe { $to_op(self) as $tpe } fn $fromfn(x: $tpe) -> Self { $from_op(x) } )* fn zero() -> Self {$from_op(0)} fn one() -> Self {$from_op(1)} fn powint(&self, n: i64) -> Self {$pow(self, n)} }; } macro_rules! impl_integer { ($($tpe:ident),*) => { $( impl Int for $tpe { impl_integer_functions!( |s: &Self| *s, |x| x as $tpe, |s: &Self, n: i64| s.pow(n as u32) ); } )* }; } impl_integer!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize); } }