#define _GLIBCXX_DEBUG
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;
using ll = long long; using pii = pair<int, int>; using vi = vector<int>; using vvi = vector<vi>; using vl = vector<ll>;
#define rep0(TMS) for (int CNT = 0; CNT < (int)(TMS); CNT++)
#define rep(CNT, GOAL) for (int CNT = 0; CNT < (int)(GOAL); CNT++)
#define rep2(CNT, START, GOAL) for (int CNT = (int)(START); CNT < (int)(GOAL); CNT++)
#define rep3(CNT, START, GOAL) for (int CNT = (int)(START); CNT > (int)(GOAL); CNT--)
#define all(CONT) begin(CONT), end(CONT)
#define itrep(ITR, CONT) for (auto ITR = begin(CONT); ITR != end(CONT); ITR++)
#define itrep1(ITR, CONT) for (auto ITR = next(begin(CONT)); ITR != end(CONT); ITR++)
template <typename T> bool chmax(T &a, const T &b) { if (a < b) { a = b; return true; } return false; }
template <typename T> bool chmin(T &a, const T &b) { if (a > b) { a = b; return true; } return false; }
void prec(const int &DIG) { cerr << fixed << setprecision(DIG); cout << fixed << setprecision(DIG); }
template <typename T> void CERR(const T &ELEM) { cerr << ELEM; }
template <typename T, typename ...Ts> void CERR(const T &FIRST, const Ts &...REST) { CERR(FIRST); cerr << ", "; CERR(REST...); }
template <typename T1, typename T2> void CERR(const pair<T1, T2> &PAIR) { cerr << "("; CERR(PAIR.first); cerr << ", "; CERR(PAIR.second); cerr << ")"; }
template <typename T> void CERR(const vector<T> &VEC) { cerr << "{ "; itrep(ITR, VEC) { CERR(*ITR); cerr << ", "; } cerr << "}"; }
template <typename T> void CERR1(const vector<T> &VEC) { cerr << "{ "; itrep1(ITR, VEC) { CERR(*ITR); cerr << ", "; } cerr << "}"; }
template <typename T> void CERR(const set<T> &SET) { cerr << "{ "; itrep(ITR, SET) { CERR(*ITR); cerr << ", "; } cerr << "}"; }
template <typename T> void CERR(const multiset<T> &MULTISET) { cerr << "{ "; itrep(ITR, MULTISET) { CERR(*ITR); cerr << ", "; } cerr << "}"; }
template <typename T1, typename T2> void CERR(const map<T1, T2> &MAP) { cerr << "{ "; itrep(ITR, MAP) { CERR(*ITR); cerr << ", "; } cerr << "}"; }
#define db(OBJ) cerr << #OBJ << ": "; CERR(OBJ); cerr << ", "
#define dbl(OBJ) cerr << #OBJ << ": "; CERR(OBJ); cerr << "\n"
#define db1(OBJ) cerr << #OBJ << ": "; CERR1(OBJ); cerr << "\n"
#define dbs(...) cerr << "(" << #__VA_ARGS__ << "): ("; CERR(__VA_ARGS__); cerr << ")\n"
#define dbvv(VV) cerr << #VV << ": {\n"; rep(CNT, VV.size()) { cerr << #VV << "[" << CNT << "]: "; CERR(VV[CNT]); cerr << ",\n"; } cerr << "}\n"
#define db01(VV) cerr << #VV << ": {\n"; rep(CNT, VV.size()) { cerr << #VV << "[" << CNT << "]: "; CERR1(VV[CNT]); cerr << ",\n"; } cerr << "}\n"
#define db10(VV) cerr << #VV << ": {\n"; rep2(CNT, 1, VV.size()) { cerr << #VV << "[" << CNT << "]: "; CERR(VV[CNT]); cerr << ",\n"; } cerr << "}\n"
#define db11(VV) cerr << #VV << ": {\n"; rep2(CNT, 1, VV.size()) { cerr << #VV << "[" << CNT << "]: "; CERR1(VV[CNT]); cerr << ",\n"; } cerr << "}\n"
#define YN(FLG) cout << (FLG ? "YES" : "NO") << "\n"
#define Yn(FLG) cout << (FLG ? "Yes" : "No") << "\n"
#define yn(FLG) cout << (FLG ? "yes" : "no") << "\n"
// const ll INF = 1'000'000'000'000'000'007;
const int INF = 1'000'000'007;
const ll MOD = 1'000'000'007; // 998'244'353;

ll rem(ll x) { x %= MOD; if (x < 0) x += MOD; return x; }
ll mpow(ll x, ll n) { ll res = 1; x = rem(x); while (n > 0) { if (n & 1) res = rem(res * x); x = rem(x * x); n >>= 1; } return res; }
ll minv(ll x) { assert(x = rem(x)); return mpow(rem(x), MOD - 2); }

struct mint {
	ll val;
	ll mpow(ll x, ll n) { ll res = 1; x = rem(x); while (n > 0) { if (n & 1) res = rem(res * x); x = rem(x * x); n >>= 1; } return res; }
	ll minv(ll x) { assert(x = rem(x)); return mpow(rem(x), MOD - 2); }
	mint() { val = 0; }
	mint(ll val_) { val = rem(val_); }
	mint(const mint &other) { val = other.val; }
	mint operator=(ll val_) { val = rem(val_); return *this; }
	mint operator=(const mint &other) { val = other.val; return *this; }
	mint operator+(ll y) { return mint(val + rem(y)); }
	mint operator+(const mint &other) { return operator+(other.val); }
	void operator+=(ll y) { val = rem(val + rem(y)); }
	void operator+=(const mint &other) { operator+=(other.val); }
	mint operator-() { return mint(-val); }
	mint operator-(ll y) { return mint(val - rem(y)); }
	mint operator-(const mint &other) { return operator-(other.val); }
	void operator-=(ll y) { val = rem(val - rem(y)); }
	void operator-=(const mint &other) { operator-=(other.val); }
	mint operator*(ll y) { return mint(val * rem(y)); }
	mint operator*(const mint &other) { return operator*(other.val); }
	void operator*=(ll y) { val = rem(val * rem(y)); }
	void operator*=(const mint &other) { operator*=(other.val); }
	mint mpow(ll n) { return mint(mpow(val, n)); }
	mint mpow(const mint &other) { return mpow(other.val); }
	mint minv() { return mint(minv(val)); }
	mint operator/(ll y) { return mint(val * minv(y)); }
	mint operator/(const mint &other) { return operator/(other.val); }
	void operator/=(ll y) { val = rem(val * minv(y)); }
	void operator/=(const mint &other) { operator/=(other.val); }
};

struct fpc {
	vector<mint> facts;
	fpc() {};
	fpc(ll n) {
		facts = vector<mint>(n + 1, mint(1));
		rep2(k, 1, n + 1) facts[k] = facts[k - 1] * k;
	}
	mint fact(ll k) { return facts[k]; }
	mint perm(ll n, ll r) { return facts[n] / facts[n - r]; }
	mint comb(ll n, ll r) { return facts[n] / (facts[r] * facts[n - r]); }
};

// 「i != j のとき Ai != Aj かつ Bi != Bj」 を満たす数列の組(A, B)の数考える。
// 包除原理を用いて，そのうち Ai != Bi を満たすものの個数を求める。
// K個「以上」のiについて Ai = Bi となるものの数P_K(0<=i<=_K)は，
// iの選び方が comb(N, K)通り，このK個の整数の選び方が perm(M, K)通り，
// 残る(N-K)個のiについての整数の選び方は，Aについて，perm(M-K, N-K)通り，
// Bについて，perm(M-K, N-K)通り。
// よって，P_K = comb(N, K) * perm(M, K) * perm(M-K, N-K)^2.
// (-1)^K * P_K をK=0..Nについて足し合わせればよい。

int N, M;
fpc f;
mint P(int K) {
	return f.comb(N, K) * f.perm(M, K) * f.perm(M - K, N - K).mpow(2);
}

int main() {
	cin >> N >> M;
	f = fpc(M);
	mint ans = 0;
	rep(K, N + 1) {
		if (K % 2 == 0) ans += P(K);
		else ans -= P(K);
	}
	cout << ans.val << endl;
}

Measured memory_bytes: 7084