#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define pb push_back
#define mp make_pair
const int MAXN=205;
const ll mod = 1000000007;

ll gc(ll a,ll b)
{
    if(b==0) return a;
    return gc(b,a%b);
}
ll power(ll x, ll y, ll p)
{
    ll res = 1;     // Initialize result

    x = x % p; // Update x if it is more than or
                // equal to p

    if (x == 0) return 0; // In case x is divisible by p;

    while (y > 0)
    {
        // If y is odd, multiply x with result
        if (y & 1)
            res = (res*x) % p;

        // y must be even now
        y = y>>1; // y = y/2
        x = (x*x) % p;
    }
    return res;
}

vector<bool>prime(100005,true);
vector<ll>v;
void sieve(ll n)
{
    prime[1]=false;
   for (int p=2; p*p<=n; p++)
    {
        // If prime[p] is not changed, then it is a prime
        if (prime[p] == true)
        {
            // Update all multiples of p greater than or
            // equal to the square of it
            // numbers which are multiple of p and are
            // less than p^2 are already been marked.
            for (int i=p*p; i<=n; i += p)
                prime[i] = false;
        }
    }

    for(int i=2;i<=n;i++)
    {
        if(prime[i]==true)
            v.push_back(i);
    }
}

bool comp(pair<ll,ll> &p1, pair<ll,ll> &p2)
{
    return (p1.second<p2.second);
}
int BIT[1000];
void update(int x, int delta)
{
    int n;
      for(; x <= n; x += x&-x)
        BIT[x] += delta;
}
int query(int x)
{
     int sum = 0;
     for(; x > 0; x -= x&-x)
        sum += BIT[x];
     return sum;
}

vector<vector<ll> >dp(30005,vector<ll>(248,-1));


void lcs()
{
vector<int> d;
int ans, n;
 for (int i = 0; i < n; i++) {
        int x;
        scanf("%d", &x);
        vector<int>::iterator it = upper_bound(d.begin(), d.end(), x);
        if (it == d.end()) d.push_back(x);
        else *it = x;
    }
    printf("LIS = %d", d.size());
}

ll dfs(ll src,ll p, vector<ll> adj[],vector<ll>& sz)
{
    sz[src]=1;
    for(int i=0;i<adj[src].size();i++)
    {
        ll v=adj[src][i];
        if(v==p) continue;
        sz[src]+=dfs(v, src,adj,sz);
    }
    return sz[src];
}
void dfs2(ll src , ll p, vector<ll> adj[], vector<ll> & dp, vector<ll>& ans, ll m)
{
    ans[src]=dp[src];
    for(int i=0;i<adj[src].size();i++)
    {
        ll v=adj[src][i];
        if(v==p) continue;
        dp[src]/=(dp[v]+1);
        dp[v]=((dp[v]%m)*(dp[src]+1)%m)%m;
        dfs2(v,src,adj,dp,ans,m
             );
        dp[v]/=(dp[src]+1);
        dp[src]=((dp[src]%m)*(dp[v]+1)%m);
    }
    return;
}

inline ll add(ll a,ll b) {return ((a%mod)+(b%mod))%mod;}
inline ll sub(ll a,ll b) {return ((a%mod)-(b%mod)+mod)%mod;}
inline ll mul(ll a,ll b) {return ((a%mod)*(b%mod))%mod;}
ll dfs1(vector<ll> adj[], ll src, ll p,ll col, vector<ll>& dp)
{
    dp[src]=1;
    for(int i=0;i<adj[src].size();i++)
    {
        ll v=adj[src][i];
        if(v==p) continue;
        ll st=dfs1(adj, v,src, 1,dp);
        if(col==1)
        {
            ll temp=0;
            temp=add(temp,dfs1(adj,v,src,0,dp));
            temp=add(temp,st);
            dp[src]=mul(dp[src],temp);
        }
        else
        {
            dp[src]=mul(dp[src],st);
        }

    }
    return dp[src];
}

ll solution( vector<ll> A, ll k)
{
    // seiz of the vector
    // which does is constant
    ll N = A.size();

    // bases cases
    if (N < k || N < 1 || k < 1)
        return 0;
    if (N == k)
        return 1;

    // Prepare arrays for recursion
    vector<ll> v1(N, 0);
    vector<ll> v2(N, 0);
    vector<ll> v3(N, 0);

    // initiate separately for k = 1
    // intiate the last element
    v2[N - 1] = 1;
    v3[A[N - 1] - 1] = 1;

    // initiate all other elements of k = 1
    for (ll i = N - 2; i >= 0; i--) {

        // initialize the front element
        // to vector v2
        v2[i] = v2[i + 1];

        // if element v[a[i]-1] is 0
        // then increment it in vector v2
        if (v3[A[i] - 1] == 0) {
            v2[i]++;
            v3[A[i] - 1] = 1;
        }
    }

    // iterate for all possible values of K
    for (ll j = 1; j < k; j++) {

        // fill the vectors with 0
        fill(v3.begin(), v3.end(), 0);

        // fill(v1.begin(), v1.end(), 0)
        // the last must be 0 as from last no unique
        // subarray can be formed
        v1[N - 1] = 0;

        // Iterate for all index from which unique
        // subsequences can be formed
        for (ll i = N - 2; i >= 0; i--) {

            // add the number of subsequence formed
            // from the next index
            v1[i] = v1[i + 1];

            // start with combinations on the
            // next index
            v1[i] = v1[i] + v2[i + 1];

            // Remove the elements which have
            // already been counted
            v1[i] = v1[i] - v3[A[i] - 1];

            // Update the number used
            v3[A[i] - 1] = v2[i + 1];
        }

        // prepare the next iteration
        // by filling v2 in v1
        v2 = v1;
    }

    // last answer is stored in v1
    return v1[0];
}
ll recur(ll idx,ll sum, vector<pair<ll,ll> >& v, vector<ll>& b, vector<ll>& pre, vector<ll>& dp)
{
    if(idx==b.size()) return 0;
    if(dp[idx]!=-1) return dp[idx];
    ll temp=INT_MAX;
    temp=min(temp,recur(idx+1,sum,v,b,pre,dp) + b[idx]);
    for(int i=0;i<v.size();i++)
    {
        ll x=v[i].first;
        ll y=v[i].second;
        if(idx+x-1>=b.size()) continue;
        ll calc= pre[idx+x-1]-pre[idx+y-1];
        temp=min(temp, recur(idx+x, sum,v,b,pre,dp)+ calc);
    }
    dp[idx]=temp;
    return temp;
}
set<pair<ll,ll> >temp;

void dfs(ll src, vector<ll>& p, vector<ll> adj[],vector<bool>& vis, vector<bool>& v)
{
    vector<ll>:: iterator it;
    vis[src]=true;
    for( it=adj[src].begin();it!=adj[src].end();it++)
    {
        if((*it)==p[src]) continue;

        if(!vis[*it])
        {
            p[*it]=src;
            dfs((*it), p,adj, vis,v);
        }
        else
        {
        if(v[*it]==true) continue;
        else
        {
            ll c=(*it);
            ll d=src;
            temp.insert(mp(c,d));
            v[c]=true;
            v[d]=true;
            ll coun=1;
            while(d!=c)
            {
                temp.insert(mp(d,p[d]));
                coun++;
                v[p[d]]=true;
                d=p[d];
            }

        }
        }
    }
}
ll recur(ll idx,ll k, ll n)
{
    if(idx==n) return 1;
    if(idx>n) return 0;
    ll temp=0;
    temp+=recur(idx+1,k,n);
    temp+=(idx+k, k,n);
    return temp;
}
ll find(ll u, vector<ll>& parent)
{
    if(u==parent[u]) return u;
    else return parent[u]=find(parent[u],parent);
}
 void unio(ll u, ll v, vector<ll>& parent, vector<ll>& ran, map<ll,ll>& m1)
{
    u=find(u,parent);
    v=find(v,parent);
    if(u==v) return;
    if(ran[u]>=ran[v])
    {
        parent[v]=u;
        ran[u]+=v;
        m1[u]+=m1[v];
    }
    else{
        parent[u]=v;
        ran[v]+=u;
        m1[v]+=m1[u];
    }
}
ll dfs(ll src, ll p, vector<ll>& a, vector<pair<ll,ll> > adj[], vector<ll>& dp)
{
    ll can1=0;
    ll can2=0;
    vector<pair<ll,ll> >:: iterator it;
    for(it=adj[src].begin();it!=adj[src].end();it++)
    {
        if(((*it).first==p)) continue;
        ll st=max(0LL,dfs((*it).first,src,a,adj,dp)- (*it).second);
        if(st>can1)
        {
            can2=can1;
            can1=st;
        }
        else if(st>can2)
        {
            can2=st;
        }
    }
    dp[src]=a[src]+ can1+can2;
    return (max(can1,can2)+ a[src]);
}
ll ans=0;
vector<vector<ll> >col(1003,vector<ll>(1003,-1));
vector<vector<ll> >store(1003,vector<ll>(1003,-1));
ll dfs( vector<vector<char> >& c, vector<vector<bool> >& vis, ll temp, ll i , ll j, bool &check, char ch, ll color)
{
    if(i<0 || j<0 || i>=vis.size() || j>=vis[0].size())
        return temp;
    if(ch=='A' && c[i][j]!='D') return temp;
    if(ch=='D' && c[i][j]!='I') return temp;
    if(ch=='I' && c[i][j]!='M') return temp;
    if(ch=='M' && c[i][j]!='A') return temp;
    if(vis[i][j])
    {
        if(c[i][j]=='D' && color==col[i][j])
        {
            check=true;
            cout<<color<<" "<<i<<" "<<j<<endl;
            return 0;
        }
    }
    if(dp[i][j]!=-1) return dp[i][j];
    col[i][j]=color;
    vis[i][j]=true;
    ll cac=0;
    if(c[i][j]=='A')
    {
        ans=max(ans,temp+1);
       cac= max(cac, dfs(c,vis,temp+1,i-1,j, check, c[i][j],color));
     cac=max(cac,dfs(c,vis,temp+1,i+1,j, check,c[i][j],color));
     cac=max(cac,dfs(c,vis,temp+1,i,j+1, check,c[i][j],color));
       cac=max(cac,dfs(c,vis,temp+1,i,j-1, check, c[i][j],color));
    }
     cac=max(cac,dfs(c,vis,temp,i-1,j, check, c[i][j],color));
      cac=max(cac,dfs(c,vis,temp,i+1,j, check,c[i][j],color));
      cac=max(cac,dfs(c,vis,temp,i,j+1, check,c[i][j],color));
       cac=max(cac,dfs(c,vis,temp,i,j-1, check, c[i][j],color));

      dp[i][j]=max(0LL, cac-temp);
      return cac;
}
ll dp2[101][2002];
ll ans1=0;
vector<ll>ret;
ll recur(ll idx, vector<pair<pair<ll,ll>,pair<ll,ll> > >& v , ll limit, vector<ll>store, ll p)
{
    if(p>ans1)
        {
            ans1=p;
            ret=store;
        }
    if(idx==v.size())
    {
        return 0;
    }
    ll temp=0;
    if(dp2[idx][limit]!=-1) return dp2[idx][limit];
    temp=max(temp,recur(idx+1,v, limit,store,p));
    if(limit+v[idx].second.first<v[idx].first.first)
    {
        store.push_back(v[idx].first.second);
    temp=max(temp, v[idx].second.second + recur(idx+1,v,limit + v[idx].second.first,store,p+v[idx].second.second));

    }
    dp2[idx][limit]=temp;
    return temp;
}
int main() {
 ios_base::sync_with_stdio(false);

    cin.tie(NULL);
   ll n,k;
   cin>>n>>k;

   vector<ll>fac(k+1);
   for(int i=1;i<=k;i++)
   {
       for(int j=i;j<=k;j+=i)
       {
           fac[i]++;

       }
   }
   ll ret=0;
   //for(int i=1;i<=k;i++)
   // cout<<fac[i]<<" "<<ans[i]<<endl;
   vector<ll>temp(k+1);
   for(ll i=1;i<=k;i++)
    temp[i]=power(fac[i],n,mod);
    vector<ll>dp(k+1,0);
   for(int i=k;i>=1;i--)
   {
      dp[i]=temp[i];
       for(int j=i*2;j<=k;j+=i)
       {

        dp[i]=sub(dp[i],dp[j]);

       }


   ll next=mul(dp[i],i);
   ret=add(ret,next);
 // cout<<ret<<endl;
   }
   cout<<ret;
    return 0;
}


Measured memory_bytes: 80788