Problem: Mashmokh's boss, Bimokh, didn't like Mashmokh. So he fired him. Mashmokh decided to go to university and participate in ACM instead of finding a new job. He wants to become a member of Bamokh's team. In order to join he was given some programming tasks and one week to solve them. Mashmokh is not a very experienced programmer. Actually he is not a programmer at all. So he wasn't able to solve them. That's why he asked you to help him with these tasks. One of these tasks is the following.

A sequence of l integers b1, b2, ..., bl (1 ≤ b1 ≤ b2 ≤ ... ≤ bl ≤ n) is called good if each number divides (without a remainder) by the next number in the sequence. More formally <image> for all i (1 ≤ i ≤ l - 1).

Given n and k find the number of good sequences of length k. As the answer can be rather large print it modulo 1000000007 (109 + 7).

Input

The first line of input contains two space-separated integers n, k (1 ≤ n, k ≤ 2000).

Output

Output a single integer — the number of good sequences of length k modulo 1000000007 (109 + 7).

Examples

Input

3 2


Output

5


Input

6 4


Output

39


Input

2 1


Output

2

Note

In the first sample the good sequences are: [1, 1], [2, 2], [3, 3], [1, 2], [1, 3].

Solution (in JAVA):

Solution:

import java.awt.List;
import java.io.*;
import java.util.*;




/*
 * kishan Thesiya
 * daiict
 * kishanthesiya25@gmail.com
 * 
 * 
 */


public class Main {
	FastScanner in;
	PrintWriter out;

	static ArrayList[] adj;
	static int n;
	static int x;
	static int visited[][];
	static int Ad[];
	static int Bd[];

	static int brr[][];
	static int a;
	static int b;
	static int parent[];
	static int size[];
	long mod = (long)1e9+7;
//Segment tree do not delete
	static int arr[];	
	static int d[];
	static int h;
// till now	

	class Segment{
	  private  int Lazy[];
	  private  int SegTree[];
	    void ans(){
	   
	    	
	     int x = (int) (Math.ceil(Math.log(100000) / Math.log(2)));
	        int max_size = 2 * (int) Math.pow(2, x) - 1;
	        SegTree = new int[max_size]; // allocate memory
	        Lazy = new int[max_size];
	        int n=in.nextInt();
	        int q=in.nextInt();
	        
	       
	        
	        for(int i = n-1;i<2*n-1;i++){
	        	SegTree[i] = in.nextInt();
	        }
	  
	        build_ST(0, 0, n - 1,arr);
	  
	        for(int i = 0;i<2*n;i++){
	        	System.out.println(SegTree[i]);
	        }
	        
	        while(q-->0)
	        {
	          
	        }
	    }
	    
	    
	 void build_ST(int node, int start, int end, int arr[]) 
	   {
	    if(start > end) return; 
	  	if(start == end) { // Leaf node
	    		 // Init value
			return;
		}
		int mid=(start + end) >> 1;
		build_ST(node*2+1, start, mid, arr); // Init left child
		build_ST(node*2+2, 1+mid, end, arr); // Init right child
		SegTree[node] = Math.max(SegTree[node*2+1],SegTree[node*2+2]); // Init root value
	}
	    void update_ST(int node, int start, int end, int l, int r, int diff) {
	        if(Lazy[node] != 0)
	        {
	            int pending = Lazy[node];
	            
	            SegTree[node] -= pending;
	            
	           if(start != end)
	            {
	                Lazy[2 * node + 1] += Lazy[node];
	                Lazy[2 * node + 2] += Lazy[node];
	            }
	           Lazy[node] = 0;
	        }
	        if (end < l || start > r)
	            return ;
	          if(l<=start && end<=r)
	        {
	        	  SegTree[node] -= diff;
	               
	            if(start != end) // not a leaf
	            {
	                Lazy[2*node+1] += diff;
	                Lazy[2*node+2] += diff;
	            }
	            return;
	        }
	        int mid=(start + end) >> 1;
		update_ST(node*2+1, start, mid, l, r, diff); // Updating left child
		update_ST(2+node*2, 1+mid, end, l, r, diff); // Updating right child
	
		SegTree[node] = Math.max(SegTree[node*2+1],SegTree[node*2+2]); 
		
	    }
	      int getMaxST(int start, int end, int l, int r, int node)
	    {
	    	  if(Lazy[node] != 0)
		        {
		            int pending = Lazy[node];
		            
		            SegTree[node] -= pending;
		            
		           if(start != end)
		            {
		                Lazy[2 * node + 1] += Lazy[node];
		                Lazy[2 * node + 2] += Lazy[node];
		            }
		           Lazy[node] = 0;
		        }
	        if (l <= start && r >= end)
	            return SegTree[node];
	         if (end < l || start > r)
	            return 0;
	        int mid = (start + end) >> 1;
	        return Math.max(getMaxST(start, mid, l, r, 2 * node + 1),getMaxST(mid + 1, end, l, r, 2 * node + 2));
	    }
	      
	}
	
	static class Pair implements Comparable<Pair>
    {
        long x;
        long y;
        
        Pair(long l, long m) {
            this.x = l;
            this.y = m;
        }
        
        public int compareTo(Pair p) {
            if (this.x == p.x) {
                return (int)(p.y - this.y);
            }
            return (int)(this.x - p.x);
        }
        
        public String toString(){
        	return x + " " + y;
        }
        
        public boolean equals(Object o){
        	if(o instanceof Pair){
        		Pair a = (Pair)o;
        		
        		return this.x == a.x && this.y == a.y;
        	}
        	
        	return false;
        }
        
        public int hashCode(){
        	return new Long(x).hashCode()*31 + new Long(y).hashCode();
        }
    
    }
    
	
	public static int gcd(int a, int b) {
		if (b == 0) return a;
		return gcd(b, a%b);
	}
	
	public static int find(int i){
		if(parent[i] != i){
			return find(parent[i]);
		}
		
		return i;
	}
	
	
	public static void union(int a,int b){
		int ra = find(a);
		int rb = find(b);

		if(ra!= rb){
			if(size[ra] > size[rb]){
				parent[rb] =ra;
				size[ra] += size[rb];
			}else{
				parent[ra] = rb;
				size[rb] += size[ra];
			}
		}
		
	}

	public static void apply(int p,int value){
		arr[p] += value;
		
		if(p < n){
			d[p] += value;
		}
	}
	
	public static void push(int p){
		
		for(int s = h;s>0;s--){
			int i = p >> s;
			
			if(d[i] != 0){
				apply(i<<1,d[i]);
				apply(i<<1|1,d[i]);
				d[i] = 0;
			}		
		}		
	}
	
	public static void lazybuild(int p){
		while(p > 1){
			p>>=1;
			arr[p] = Math.max(arr[p<<1], arr[p<<1|1]) + d[p];
		}
	}
	
	public static void lazyupdate(int l,int r,int value){
		l += n; r += n+1;		
		int l0 = l;int r0 = r;
		for(;l<r; l>>=1,r>>=1){
			if((l&1) == 1){
				apply(l++,value);
			}
			
			if((r&1) == 1){
				apply(--r,value);
			}
		}
		lazybuild(l0);
		lazybuild(r0-1);
			
	}
	
	public static int lazyquery(int l,int r){
		l += n;r += n+1;
		push(l);push(r-1);
		int res = (int)-2e9;
		
		for(;l<r;l>>=1,r>>=1){
			if((l&1) == 1){
				res = Math.max(arr[l++], res);
			}
			
			if((r&1) == 1){
				res = Math.max(arr[--r], res);
			}
		}
		
		return res;
	}
	
	public static void build(){
		
		for(int i = n-1;i>0;i--){
			arr[i] = Math.max(arr[i<<1], arr[i<<1|1]);
		}
		
	}
	
	public static void update(int p,int v){
		
		for(arr[p += n] = v; p>0; p>>=1 ){
			arr[p>>1] = Math.max(arr[p], arr[p^1]);
		}
		
	}
	
	public static int query(int l,int r){
		
		r++;
		int max = 0;
		for(l +=n,r +=n;l<r; l>>=1,r>>=1 ){
			
		
			
			if((l&1) == 1){
				max = Math.max(max, arr[l++]);
			}
			
			if((r&1) == 1){
				max = Math.max(max, arr[--r]);
			}
		}
		
		return max;
	}
	
	void multiply(long a[][], long b[][])
	{
	    
	    long mul[][] = new long[3][3];
	    for (int i = 0; i < 3; i++)
	    {
	        for (int j = 0; j < 3; j++)
	        {
	            mul[i][j] = 0;
	            for (int k = 0; k < 3; k++)
	                mul[i][j] = (int) ((mul[i][j] + (a[i][k]*b[k][j])%mod)%mod);
	        }
	    }
	 
	  
	    for (int i=0; i<3; i++)
	        for (int j=0; j<3; j++)
	            a[i][j] = mul[i][j];  
	}
	
	long power(long F[][], long n)
	{
	    long M[][] = {{1,1,0}, {1,0,0}, {0,1,0}};
	 
	    if (n==1)
	        return (long) ((F[0][0] + F[0][1])%mod);
	 
	    power(F, n/2);
	 
	    multiply(F, F);
	 
	    if (n%2 != 0)
	        multiply(F, M);
	 
	    return (long) ((F[0][0] + F[0][1])%mod) ;
	}
	 
	
	long findNthTerm(long n)
	{
	    long[][] F = {{1,1,0}, {1,0,0}, {0,1,0}} ;
	 
	    return power(F, n);
	}
	 
	
    void solve() throws NumberFormatException, IOException {
 
    	Scanner in = new Scanner(System.in);
   
//    	n = in.nextInt();
//    	arr = new int[2*n];
//    	d = new int[n];
//    	h = (int)Math.ceil((Math.log(n)/Math.log(2)));
//    	for(int i = 0;i<n;i++){
//    		arr[i+n] = in.nextInt();
//    	}
//    	
//    	build();
    	
    	int n = in.nextInt();
    	int k = in.nextInt();
    	
    	long dp[][] = new long[2001][2001];
    	
    	ArrayList<Integer> list[] = new ArrayList[n+1];
    	
    	for(int i = 0;i<=n;i++)
    		list[i] = new ArrayList();
    	
    	for(int i = 1;i<=n;i++){
    		for(int j = i;j<=n;j+=i){
    			list[j].add(i);
    		}
    	}
    	
    	for(int i = 1;i<=n;i++){
    		dp[1][i] = 1;
    	}
    	
    	for(int i = 2;i<=k;i++){
    		for(int j = 1;j<=n;j++){
    			
    			for(Integer s:list[j]){
    				dp[i][j] = ((dp[i][j] + dp[i-1][s])%mod);
    			}
    		}
    	}
    	
    	long ans = 0;
    	
    	for(int i = 1;i<=n;i++){
    		ans = (ans + dp[k][i])%mod;
    	}
    	
    	System.out.println(ans);
    	
    	
    	
//    	
//    	 BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//        
//    	 StringBuilder sb = new StringBuilder();
// 
//    	 int tests = Integer.parseInt(br.readLine().trim());
//    	  
//          while (tests-- > 0) {
//        	  
//        	  String s[] = br.readLine().split("\\*");
//        	  
//        	  int ans = 0;
//        	  
//        	  for(int i = 0;i<s.length;i++){
//        		  if(!s[i].contains("X")){
//        			  ans += s[i].length();
//        		  }
//        	  }
//        	  
//        	  sb.append(ans+"\n");
//        	 
//          }
          
          
          
          //	System.out.println(sb.toString());
          
           
         
}
    
    public static String[] reverse(String arr[]){
    	
    	
    	for(int i = 0;i<arr.length/2;i++){
    		String temp = arr[i];
    		arr[i] = arr[arr.length-i-1];
    		arr[arr.length-1-i] = temp;
    	}
    	
    	return arr;
    	
    }
	
	
    
  
    private static long ans(long n){
        if(n==1) return 2;
        n+=1;
        int cnt=-1;
        while(n%2==0){
            n/=2;
            cnt++;
        }
        if(n==1){
            return (int)Math.pow(2,cnt)-1;
        }
        return -1;
    }
    public static long sum(long x){
    	return x<10?x:x%10 + sum(x/10);
    }
	
	public static long gcd(long x, long y) {
		if (x == 0)
			return y;
		else
			return gcd( y % x,x);
	}
	public static long pow(long n,long p,long m){
        long  result = 1;
         if(p==0)
           return 1;
       if (p==1)
           return n;
       while(p!=0)
       {
           if(p%2==1)
               result *= n;
           if(result>=m)
           result%=m;
           p >>=1;
           n*=n;
           if(n>=m)
           n%=m;
       }
       return result;
       }
	
	
	
	public static boolean isPrime(int n) {
		// Corner cases
		if (n <= 1)
			return false;
		if (n <= 3)
			return true;
 
		// This is checked so that we can skip 
		// middle five numbers in below loop
		if (n % 2 == 0 || n % 3 == 0)
			return false;
 
		for (int i = 5; i * i <= n; i = i + 6)
			if (n % i == 0 || n % (i + 2) == 0)
				return false;
 
		return true;
	}
	

	void run() throws NumberFormatException, IOException {
		in = new FastScanner();
		out = new PrintWriter(System.out);

		solve();

		out.close();
	}

	class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		public FastScanner() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		String next() {
			while (st == null || !st.hasMoreTokens()) {
				try {
					st = new StringTokenizer(in.br.readLine());
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}

		int nextInt() {
			return Integer.parseInt(next());
		}

		long nextLong() {
			return Long.parseLong(next());
		}

		double nextDouble() {
			return Double.parseDouble(next());
		}
	}
	
	class Tri{
		
		Tri[] arr;
		
		public Tri(){
			arr = new Tri[27];
		}
		
	}
	
	
 

	public static void main(String[] args) throws NumberFormatException, IOException {
		new Main().run();
	}
}


class SegmentTreeRMQ
{
    long st[]; //array to store segment tree
 
    // A utility function to get minimum of two numbers
    long minVal(long x, long y) {
        return (x < y) ? y : x;
    }
 
    // A utility function to get the middle index from corner
    // indexes.
    int getMid(int s, int e) {
        return s + (e - s) / 2;
    }
 
    /*  A recursive function to get the minimum value in a given
        range of array indexes. The following are parameters for
        this function.
 
        st    --> Pointer to segment tree
        index --> Index of current node in the segment tree. Initially
                   0 is passed as root is always at index 0
        ss & se  --> Starting and ending indexes of the segment
                     represented by current node, i.e., st[index]
        qs & qe  --> Starting and ending indexes of query range */
    long RMQUtil(int ss, int se, int qs, int qe, int index)
    {
        // If segment of this node is a part of given range, then
        // return the min of the segment
        if (qs <= ss && qe >= se)
            return st[index];
 
        // If segment of this node is outside the given range
        if (se < qs || ss > qe)
            return 0;
 
        // If a part of this segment overlaps with the given range
        int mid = getMid(ss, se);
        return minVal(RMQUtil(ss, mid, qs, qe, 2 * index + 1),
                RMQUtil(mid + 1, se, qs, qe, 2 * index + 2));
    }
 
    // Return minimum of elements in range from index qs (quey
    // start) to qe (query end).  It mainly uses RMQUtil()
    long RMQ(int n, int qs, int qe)
    {
        // Check for erroneous input values
        if (qs < 0 || qe > n - 1 || qs > qe) {
         //   System.out.println("Invalid Input");
            return -1;
        }
 
        return RMQUtil(0, n - 1, qs, qe, 0);
    }
 
    // A recursive function that constructs Segment Tree for
    // array[ss..se]. si is index of current node in segment tree st
    long constructSTUtil(long arr[], int ss, int se, int si)
    {
        // If there is one element in array, store it in current
        //  node of segment tree and return
        if (ss == se) {
            st[si] = arr[ss];
            return arr[ss];
        }
 
        // If there are more than one elements, then recur for left and
        // right subtrees and store the minimum of two values in this node
        int mid = getMid(ss, se);
        st[si] = minVal(constructSTUtil(arr, ss, mid, si * 2 + 1),
                constructSTUtil(arr, mid + 1, se, si * 2 + 2));
        return st[si];
    }
 
    /* Function to construct segment tree from given array. This function
       allocates memory for segment tree and calls constructSTUtil() to
       fill the allocated memory */
    void constructST(long arr[], int n)
    {
        // Allocate memory for segment tree
 
        //Height of segment tree
        int x = (int) (Math.ceil(Math.log(n) / Math.log(2)));
 
        //Maximum size of segment tree
        int max_size = 2 * (int) Math.pow(2, x) - 1;
        st = new long[max_size]; // allocate memory
 
        // Fill the allocated memory st
        constructSTUtil(arr, 0, n - 1, 0);
    }
 
   
       
}

class Node{
	int a;
	int b;
	int c;
}

class MyComp implements Comparator<Node>{
    
	@Override
	public int compare(Node a,Node b) {
		
		// < == -1
		
		if(a.a < b.a){
			return -1;
		}else if(a.a > b.a){
			return 1;
		}else{
			return 0;
		}
		
		
	}
}