#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update
using namespace std;
using namespace __gnu_pbds;

template<class T> ostream& operator<<(ostream &os, vector<T> V){os << "[ "; for(auto v  : V) os << v << " "; return os << " ]";}
template<class T> ostream& operator<<(ostream &os, set<T> V){os << "[ "; for(auto v  : V) os << v << " "; return os << " ]";}
template<class T , class R > ostream& operator<<(ostream &os, map<T , R> V){os << "[ "; for(auto v  : V) os << "(" << v.first << ":" << v.second << ")"; return os << " ]";}
template<class T , class R > ostream& operator<<(ostream &os, pair<T , R> V){return os << "(" << V.first << "," << V.second << ")";}

#define cerr cout
#ifdef LOCAL
    #define TRACE
#endif
#ifdef TRACE
    #define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
    template <typename Arg1>
    void __f(const char* name, Arg1&& arg1){cerr << "T->";cerr << name << " : " << arg1 << endl;}
    template <typename Arg1, typename... Args>
    void __f(const char* names, Arg1&& arg1, Args&&... args){cerr << "T->";const char* comma = strchr(names + 1, ','); cerr.write(names, comma - names) << " : " << arg1<<" | "; __f(comma+1, args...);}
    clock_t clk=clock();
    #define checktime() cout<<"\nTime Elapsed : "<<float(clock()-clk)/CLOCKS_PER_SEC<<endl
#else
    #define trace(...);
    #define checktime();
#endif
/*---------------------------Defines----------------------*/
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;
// find_by_order(k)  returns iterator to kth element starting from 0;
// order_of_key(k) returns count of elements strictly smaller than k;
typedef long long int ll;
typedef long double ld;

#define d0(x) cout<<(x)<<" "
#define d1(x) cout<<(x)<<"\n"
#define d2(x,y) cout<<(x)<<" "<<(y)<<"\n"
#define d3(x,y,z) cout<<(x)<<" "<<(y)<<" "<<(z)<<"\n"
#define d4(a,b,c,d) cout<<(a)<<" "<<(b)<<" "<<(c)<<" "<<(d)<<"\n"
#define d5(a,b,c,d,e) cout<<(a)<<" "<<(b)<<" "<<(c)<<" "<<(d)<<" "<<(e)<<"\n"
#define d6(a,b,c,d,e,f) cout<<(a)<<" "<<(b)<<" "<<(c)<<" "<<(d)<<" "<<(e)<<" "<<(f)<<"\n"
// Use max({a,b,c,d,....}) instead
// #define max3(a,b,c) max(max((a),(b)),(c))
// #define max4(a,b,c,d) max(max((a),(b)),max((c),(d)))

#define pll pair<ll,ll>
#define pb push_back
#define F first
#define S second
#define I insert
#define vll vector<ll>
#define vbl vector<bool>
#define vvll vector<vll>
#define vld vector<ld>
#define vb vector<bool>
#define vc vector<char>
#define vpll vector<pll>
#define all(x) (x).begin(), (x).end()
/*-----------------------Modular Arithmetic---------------*/
inline ll add(ll x,ll y,ll mod){x+=y; if(x>=mod) return x-mod; return x;}
inline ll sub(ll x,ll y,ll mod){x-=y; if(x<0) return x+mod; return x;}
inline ll mul(ll x,ll y,ll mod){return (x*1ll*y)%mod;}
inline ll power(ll x,ll y,ll mod){ll ans=1; while(y){if(y&1) ans=mul(ans,x,mod); x=mul(x,x,mod); y>>=1;} return ans;}
inline ll inv(ll x,ll mod){return power(x,mod-2,mod);}
/*-----------------------------Code begins----------------------------------*/

const ll M1=1e9+7,M2=998244353;
const ll N=5e5+10;

vll fact(N),invf(N);
void pre(){
    fact[0]=1;
    invf[0]=1;
    for(ll i=1;i<N;i++){
        fact[i]=mul(fact[i-1],i,M1);
        invf[i]=mul(invf[i-1],inv(i,M1),M1);
    }
}
ll ncr(ll n, ll r){
    return mul(fact[n],mul(invf[r],invf[n-r],M1),M1);
}
void solve(){
    ll n,m;cin>>n>>m;
    ll ans=0;
    for(ll i=0;i<=n;i++){
        if(i%2) ans=sub(ans,mul(ncr(n,i),mul(ncr(m-i,n-i),fact[n-i],M1),M1),M1);
        else ans=add(ans,mul(ncr(n,i),mul(ncr(m-i,n-i),fact[n-i],M1),M1),M1);
        trace(i,ans);
    }
    ans=mul(ans,mul(ncr(m,n),fact[n],M1),M1);
    d1(ans);
}

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cout<<fixed<<setprecision(25);
    pre();
    ll t=1;
    // cin>>t;
    for(ll tt=1;tt<=t;tt++){
        // cout<<"Test Case #"<<tt<<" :\n";
        solve();
    }
    return 0;
}

Measured memory_bytes: 11036