#![allow(unused_imports)]

pub mod pcl {
pub mod math{use num::{Num,One,Zero};use std::cmp::Ordering;use std::fmt;use std::hash::{Hash,Hasher};use std::iter::{Product,Sum};use std::marker::PhantomData;use std::mem;use std::ops::{Add,AddAssign,Div,DivAssign,Mul,MulAssign,Rem,RemAssign,Sub,SubAssign,};pub type ModintInnerType=i64;pub trait ModintConst{const MOD:ModintInnerType;}#[macro_export] macro_rules!define_modint_const{(pub const $name:ident=$value:literal;)=>{pub enum $name{}impl crate::pcl::math::ModintConst for $name{const MOD:crate::pcl::math::ModintInnerType=$value;}};}define_modint_const!{pub const MOD17=1_000_000_007;}pub type Modint17=Modint<MOD17>;pub struct Modint<C>{value:ModintInnerType,marker:PhantomData<C>,}impl<C>Modint<C>{pub unsafe fn new_unchecked(value:ModintInnerType)->Modint<C>{Modint{value,marker:PhantomData,}}pub fn inner(self)->ModintInnerType{self.value}}impl<C:ModintConst>Modint<C>{pub fn new(mut value:ModintInnerType)->Modint<C>{assert_ne!(C::MOD,0,"MOD is 0");if value<0{let m=(-value)/C::MOD;value+=(m+1)*C::MOD;}unsafe{Modint::new_unchecked(value%C::MOD)}}pub fn inv(self)->Modint<C>{let mut a=self.value;let mut modulo=C::MOD;let mut u=1;let mut v=0;while modulo>0{let t=a/modulo;a-=t*modulo;u-=t*v;mem::swap(&mut a,&mut modulo);mem::swap(&mut u,&mut v);}Modint::new(u)}}impl<C:ModintConst>PartialEq for Modint<C>{fn eq(&self,other:&Self)->bool{self.inner()==other.inner()}}impl<C:ModintConst>PartialOrd for Modint<C>{fn partial_cmp(&self,other:&Self)->Option<Ordering>{self.inner().partial_cmp(&other.inner())}}impl<C:ModintConst>Eq for Modint<C>{}impl<C:ModintConst>Ord for Modint<C>{fn cmp(&self,other:&Self)->Ordering{self.inner().cmp(&other.inner())}}impl<C:ModintConst>Hash for Modint<C>{fn hash<H:Hasher>(&self,state:&mut H){self.inner().hash(state);}}impl<C>fmt::Debug for Modint<C>{fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{write!(f,"{}",self.inner())}}impl<C>Clone for Modint<C>{fn clone(&self)->Self{*self}}impl<C>Copy for Modint<C>{}impl<C:ModintConst>AddAssign for Modint<C>{fn add_assign(&mut self,rhs:Modint<C>){self.value+=rhs.value;if self.value>=C::MOD{self.value-=C::MOD;}}}impl<C:ModintConst>SubAssign for Modint<C>{fn sub_assign(&mut self,rhs:Modint<C>){self.value-=rhs.value;if self.value<0{self.value+=C::MOD;}}}impl<C:ModintConst>MulAssign for Modint<C>{fn mul_assign(&mut self,rhs:Modint<C>){self.value*=rhs.value;self.value%=C::MOD;}}impl<C:ModintConst>DivAssign for Modint<C>{fn div_assign(&mut self,rhs:Modint<C>){if rhs.value==0{panic!("attempted to divide by zero");}*self*=rhs.inv();}}impl<C:ModintConst>RemAssign for Modint<C>{fn rem_assign(&mut self,rhs:Modint<C>){if rhs.value==0{panic!("attempted to divide by zero.")}self.value%=rhs.value;}}macro_rules!impl_arith_by_assign{(impl $trait:ident::$fnname:ident{use $op:tt;})=>{impl<C:ModintConst>$trait for Modint<C>{type Output=Modint<C>;fn $fnname(mut self,rhs:Modint<C>)->Modint<C>{self $op rhs;self}}};}impl_arith_by_assign!(impl Add::add{use+=;});impl_arith_by_assign!(impl Sub::sub{use-=;});impl_arith_by_assign!(impl Mul::mul{use*=;});impl_arith_by_assign!(impl Div::div{use/=;});impl_arith_by_assign!(impl Rem::rem{use%=;});impl<C:ModintConst>One for Modint<C>{fn one()->Modint<C>{assert_ne!(C::MOD,1,"one()is called for Modint with MOD=1");unsafe{Modint::new_unchecked(1)}}}impl<C:ModintConst>Sum for Modint<C>{fn sum<I:Iterator<Item=Modint<C>>>(iter:I)->Modint<C>{iter.fold(Modint::zero(),Add::add)}}impl<C:ModintConst>Product for Modint<C>{fn product<I:Iterator<Item=Modint<C>>>(iter:I)->Self{iter.fold(Modint::one(),Mul::mul)}}impl<C:ModintConst>Zero for Modint<C>{fn zero()->Modint<C>{unsafe{Modint::new_unchecked(0)}}fn is_zero(&self)->bool{self.inner()==0}}impl<C>fmt::Display for Modint<C>{fn fmt(&self,b:&mut fmt::Formatter)->fmt::Result{write!(b,"{}",self.inner())}}impl<C:ModintConst>Num for Modint<C>{type FromStrRadixErr=<ModintInnerType as Num>::FromStrRadixErr;fn from_str_radix(src:&str,radix:u32)->Result<Self,Self::FromStrRadixErr>{ModintInnerType::from_str_radix(src,radix).map(Modint::new)}}}pub mod sum{use crate::pcl::traits::Group;use std::cmp;use std::ops::{Bound,RangeBounds};pub struct CumSum<T>{sum:Vec<T>,}impl<T:Group+Copy>CumSum<T>{pub fn from_array<A:AsRef<[T]>>(array:A)->CumSum<T>{let array=array.as_ref();let mut sum=vec![T::zero();array.len()+1];for i in 1..=array.len(){unsafe{*sum.get_unchecked_mut(i)=*sum.get_unchecked(i-1)+*array.get_unchecked(i-1);}}CumSum{sum}}pub fn sum<R:RangeBounds<usize>>(&self,range:R)->T{let orig_len=self.sum.len()-1;let start=range_start(&range,0);let end=range_end(&range,orig_len);if end<=start{return T::zero();}unsafe{*self.sum.get_unchecked(end)-*self.sum.get_unchecked(start)}}}pub struct CumSum2D<T>{sum:Vec<Vec<T>>,}impl<T:Group+Copy>CumSum2D<T>{pub fn from_matrix<M,A>(matrix:M)->CumSum2D<T>where M:AsRef<[A]>,A:AsRef<[T]>,{let array=matrix.as_ref();let height=array.len();if height==0{return CumSum2D{sum:vec![vec![T::zero()]],};}let width=unsafe{array.get_unchecked(0)}.as_ref().len();let mut sum=vec![vec![T::zero();width+1];height+1];for i in 1..=height{for j in 1..=width{assert_eq!(unsafe{array.get_unchecked(i-1)}.as_ref().len(),width,"the array's length is differ line by line");unsafe{*sum.get_unchecked_mut(i).get_unchecked_mut(j)=*sum.get_unchecked(i-1).get_unchecked(j)+*sum.get_unchecked(i).get_unchecked(j-1)-*sum.get_unchecked(i-1).get_unchecked(j-1)+*array.get_unchecked(i-1).as_ref().get_unchecked(j-1)}}}CumSum2D{sum}}pub fn sum<RY,RX>(&self,yrange:RY,xrange:RX)->T where RY:RangeBounds<usize>,RX:RangeBounds<usize>,{let orig_height=self.sum.len()-1;let orig_width=unsafe{self.sum.get_unchecked(0).len()}-1;let ystart=range_start(&yrange,0);let yend=range_end(&yrange,orig_height);let xstart=range_start(&xrange,0);let xend=range_end(&xrange,orig_width);if yend<=ystart||xend<=xstart{return T::zero();}unsafe{*self.sum.get_unchecked(yend).get_unchecked(xend)+*self.sum.get_unchecked(ystart).get_unchecked(xstart)-*self.sum.get_unchecked(ystart).get_unchecked(xend)-*self.sum.get_unchecked(yend).get_unchecked(xstart)}}}fn range_start<R:RangeBounds<usize>>(range:&R,min:usize)->usize{let start=match range.start_bound(){Bound::Included(&x)=>x,Bound::Excluded(&x)=>x+1,Bound::Unbounded=>0,};cmp::max(start,min)}fn range_end<R:RangeBounds<usize>>(range:&R,max:usize)->usize{let end=match range.end_bound(){Bound::Included(&x)=>x+1,Bound::Excluded(&x)=>x,Bound::Unbounded=>max,};cmp::min(end,max)}}pub mod traits{pub mod math{use num::Zero;use std::ops::{Add,Neg,Sub};pub trait Group:Add<Output=Self>+Sub<Output=Self>+Neg+Zero{}impl<T>Group for T where T:Add<Output=Self>+Sub<Output=Self>+Neg+Zero{}}pub use self::math::*;}
}

use crate::pcl::math::Modint17 as M;
use itertools::Itertools as _;
use num::pow;
use num::Zero;
use proconio::input;

fn main() {
    input! {
        (n, k): (usize, usize),
    }

    
    
    
    let mut numof = vec![M::new(0); k + 1];
    for g in (1..=k).rev() {
        
        let mut all = pow(M::new((k / g) as _), n);
        
        for h in (2 * g..=k).step_by(g) {
            all -= numof[h];
        }

        numof[g] = all;
    }

    
    let ans = numof
        .into_iter()
        .enumerate()
        .fold(M::zero(), |f, (g, m)| f + M::new(g as _) * m);
    println!("{}", ans)
}


Measured memory_bytes: 2816