use itertools::Itertools;
use proconio::input;
use std::{iter::once, mem::swap};

const MOD: i64 = 1_000_000_007;

#[derive(Clone, Copy, Debug)]
struct Modint(i64);

impl Modint {
    #[allow(dead_code)]
    pub fn with_value(x: i64) -> Self {
        Self(Self::normalize(x))
    }

    #[allow(dead_code)]
    pub fn with_value_unchecked(x: i64) -> Self {
        Self(x)
    }

    #[allow(dead_code)]
    pub fn validate(&self) -> &Self {
        assert!(0 <= self.0 && self.0 < MOD);
        &self
    }

    fn normalize(x: i64) -> i64 {
        let x = x % MOD;
        if x < 0 {
            x + MOD
        } else {
            x
        }
    }

    fn add_unchecked(x: i64, y: i64) -> i64 {
        let z = x + y;
        if MOD <= z {
            z - MOD
        } else {
            z
        }
    }

    fn sub_unchecked(x: i64, y: i64) -> i64 {
        let z = x - y;
        if x < 0 {
            z + MOD
        } else {
            z
        }
    }

    fn neg_unchecked(x: i64) -> i64 {
        if x == 0 {
            0
        } else {
            MOD - x
        }
    }

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

    fn div_unchecked(x: i64, y: i64) -> i64 {
        Self::mul_unchecked(x, Self::inv_unchecked(y))
    }

    fn inv_unchecked(mut x: i64) -> i64 {
        let mut y: i64 = MOD;
        let mut u: i64 = 1;
        let mut v: i64 = 0;
        while x != 0 {
            let q = y / x;
            y -= x * q;
            v -= u * q;
            swap(&mut x, &mut y);
            swap(&mut u, &mut v);
        }
        if v < 0 {
            v + MOD
        } else {
            v
        }
    }
}

macro_rules! impl_bop {
    (
        $(
            $bop_trait: ident::$bop_fn: ident, $bop_assign_trait: ident::$bop_assign_fn: ident, $impl: ident;
        )*
    ) => {
        $(
            impl std::ops::$bop_trait for Modint {
                type Output = Self;
                fn $bop_fn(self, rhs: Self) -> Self::Output {
                    Modint(Self::$impl(self.0, rhs.0))
                }
            }
            impl std::ops::$bop_assign_trait for Modint {
                fn $bop_assign_fn(&mut self, rhs: Self) {
                    use std::ops::$bop_trait;
                    *self = Modint::$bop_fn(*self, rhs)
                }
            }
        )*
    };
}

impl_bop! {
    Add::add, AddAssign::add_assign, add_unchecked;
    Sub::sub, SubAssign::sub_assign, sub_unchecked;
    Mul::mul, MulAssign::mul_assign, mul_unchecked;
    Div::div, DivAssign::div_assign, div_unchecked;
}

impl std::ops::Neg for Modint {
    type Output = Self;
    fn neg(self) -> Self::Output {
        Modint(Self::neg_unchecked(self.0))
    }
}

impl std::iter::Sum<Self> for Modint {
    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
        iter.fold(Modint(0), std::ops::Add::add)
    }
}

impl std::convert::From<i64> for Modint {
    fn from(x: i64) -> Self {
        Self::with_value(x)
    }
}

#[allow(unused_macros)]
macro_rules! modint {
    ($x: expr) => {
        Modint::with_value($x)
    };
}

fn main() {
    input!(n: usize, m: usize);
    let fact = once(modint!(1))
        .chain((1..=m as i64).scan(1.into(), |acc, x| {
            *acc = *acc * x.into();
            Some(*acc)
        }))
        .collect_vec();

    println!(
        "{}",
        (0..=n)
            .map(
                |i| modint!(if i % 2 == 0 { 1 } else { -1 }) * fact[n] * fact[m] * fact[m - i]
                    / (fact[m - n] * fact[m - n] * fact[i] * fact[n - i])
            )
            .sum::<Modint>()
            .0
    );
}


Measured memory_bytes: 6060