// Standard Stuff
#include <bits/stdc++.h>
using namespace std;

// Macros
#define F  first
#define S  second
#define PB push_back

// Rename Datatypes
using ll  = long long;
using ld  = long double;
using pii = pair<int,int>;

// Common Functions
ll fastpow(ll a, ll ex){ ll res = 1; while(ex){ if(ex & 1) res *= a; a *= a; ex >>= 1; } return res; }
ll fastpow(ll a, ll ex, ll m){ a %= m; ll res = 1; while(ex){ if(ex & 1) res = (a*res) % m; a = (a*a) % m; ex >>= 1; } return res; }
ll modinverse(ll a, ll m){ ll m0 = m, y = 0, x = 1; while (a > 1){ ll q = a / m; a %= m; swap(a,m); x -= q*y; swap(x,y); } if(x < 0) x += m0; return x; }

// HELPERS
//  Tedious Grid Movements
vector<pii> moves_grid = { {0,1} , {0,-1} , {1,0} , {-1,0} };
inline bool move_okay(int x, int y, int n, int m) { return 0 <= x and x < n and 0 <= y and y < m; }
//  Remember:
//   * vec.assign() GOOD; vec.resize() BAD
//   * comparator uses <

// Output, Common Containers
template <typename T> ostream& operator << (ostream &os, const vector<T> &v) { for (T i : v) os << i << ' '; return os; }
template <typename T> ostream& operator << (ostream &os, const set<T> &v)    { for (T i : v) os << i << ' '; return os; }
template <typename T, typename S> ostream& operator << (ostream &os, const pair<T,S> &v) { os << "(" << v.F << "=>" << v.S << ") "; return os; }
template <typename T, typename S> ostream& operator << (ostream &os, const map<T,S> &v)  { for (auto i : v) os << i << ' '; return os; }

// Debugging
#ifdef SANYAM1101
	#define trace(args...) do{ cerr << "TRACE ON! (Line: " << __LINE__ << ")\n"; auto _stream = istringstream{string{#args}}; d_f(_stream, args); } while(0)
	void d_f(__attribute__((unused)) istringstream& _stream) {}
	template<typename Head, typename... Tails> void d_f(istringstream& _stream, Head H, Tails... T) { string _name; _stream >> _name; if(_name.back() == ',') _name.pop_back(); cerr << "\t" << _name << " <=> [" << H << "]\n"; d_f(_stream, T...); }
#else
	#define trace(args...)
#endif


// CODE STARTS HERE

class Combinatorics {
private:

	ll MOD;
	vector<ll> fac, inv_fac;

	ll takemod(ll a){
		ll ret = a % MOD;
		if(ret < 0) ret += MOD;
		return ret;
	}

public:

	Combinatorics(int maxn, ll _MOD)
	    : MOD(_MOD), fac(maxn + 1, 1), inv_fac(maxn + 1, 1)
	{
		// fac(i) = fac(i - 1) * i
		for(int i = 1; i <= maxn; ++i)
			fac[i] = mul(fac[i - 1], i);

		// inv_fac(maxn) = (fac(maxn)) ^ (-1)
		inv_fac[maxn] = modinverse(fac[maxn], MOD);
		// inv_fac(i) / (i + 1) = inv_fac(i + 1) => inv_fac(i) = inv_fac(i + 1) * (i + 1)
		for(int i = maxn - 1; i > 1; --i)
			inv_fac[i] = mul(inv_fac[i + 1], i + 1); 
	}

	ll add(ll a, ll b){	return takemod(a + b); }
	ll mul(ll a, ll b){ return takemod(a * b); }

	ll nPr(ll n, ll r){
		if(n < r) return 0;
		return mul(fac[n], inv_fac[n - r]);
	}

	ll nCr(ll n, ll r){
		if(n < r) return 0;
		return mul(fac[n], mul(inv_fac[n - r], inv_fac[r]));
	}

	ll count_derangements_of_length_n_from_m(ll n, ll m){
		/*
		 * Principle of Inclusion-Exclusion
		 * Let S_k be number of permutations with >= k positions fixed (as given permutation).
		 * S_k = (no of ways to choose set of k positions) * (no of ways to permute (n - k) positions from (m - k) elements)
		 *     = (n)C(k) * (m - k)P(n - k)
		 * Then, Derangements = \Sigma{i = 0 ... n} [(-1) ^ i] * S_i
		 */

		ll cou = 0;

		for(int i = 0; i <= n; ++i){
			ll curr = mul(nCr(n, i), nPr(m - i, n - i));
			cou = add(cou, i & 1 ? -curr : curr);
		}

		return cou;
	}
};

void solve(){
	int n, m;
	cin >> n >> m;

	Combinatorics combi{m, (int)1e9 + 7};

	ll A = combi.nPr(m, n);
	ll B = combi.count_derangements_of_length_n_from_m(n, m);

	cout << combi.mul(A,B) << "\n";
}

signed main (void){
	// Fast_IO
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	// Set Fixed Notation (default sucks), High Precision for Floating-Point Output
	cout << fixed << setprecision(20);

	// Multiple TCs
	int tt = 1;
	// cin >> tt;
	while(tt--) solve();
}


Measured memory_bytes: 11008