Ivan has number b. He is sorting through the numbers a from 1 to 10^{18}, and for every a writes ([a,    b])/(a) on blackboard. Here [a,    b] stands for least common multiple of a and b. Ivan is very lazy, that's why this task bored him soon. But he is interested in how many different numbers he would write on the board if he would finish the task. Help him to find the quantity of different numbers he would write on the board.

Input

The only line contains one integer — b (1 ≤ b ≤ 10^{10}).

Output

Print one number — answer for the problem.

Examples

Input

1


Output

1

Input

2


Output

2

Note

In the first example [a,    1] = a, therefore ([a,    b])/(a) is always equal to 1.

In the second example [a,    2] can be equal to a or 2 ⋅ a depending on parity of a. ([a,    b])/(a) can be equal to 1 and 2.
/* package codechef; // don't place package name! */

import java.util.*;
import java.lang.*;
import java.io.*;

/* Name of the class has to be "Main" only if the class is public. */
public class Codechef
{
     
	public static void main (String[] args) throws java.lang.Exception
	{
		// your code goes here
		FastReader sc=new FastReader();
// 		constructST(a,n);RMQ(n, qs, qe)
        // sieveOfEratosthenes();
		long b=sc.nextLong(),i,ans=0;
		for(i=1;i*i<=b;i++){
		    if(b%i==0){
		        long a1=i,a2=b/i;
		        if(i*i==b)
		            ans++;
		        else {
		           ans+=2;
		        }
		    }
		}
		 System.out.println(ans);
	}
	static int lower_bound(int a[],int x){
         int n=a.length,low=0,high=n-1,res=-1;
         while(low<=high){
             int mid=(low+high)>>1;
             if(a[mid]>=x){
                res=mid;high=mid-1;
             }
             else 
                low=mid+1;
         }
         return res;
     }
      static int upper_bound(int a[],int x){
          int n=a.length,low=0,high=n-1,res=-1;
          while(low<=high){
              int mid=(low+high)>>1;
              if(a[mid]<=x){
                  res=mid;low=mid+1;
              }
              else 
                  high=mid-1;
          }
          return res;
      }
    //   static int MAX=1000001;boolean prime[] = new boolean[MAX]; 
      
    //   static void sieveOfEratosthenes() { 
    //       for(int m9=0;m9<MAX;m9++) prime[m9]=true;
    //     for(int p = 2; p*p <=n; p++) { 
    //         if(prime[p] == true) 
    //         { 
    //             // Update all multiples of p 
    //             for(int i = p*2; i <= n; i += p) 
    //                 prime[i] = false; 
    //         } 
    //     } 
    //   }
      static int st[]; 
//		Make a utility function to store minimum in a given range
		static int minVal(int x,int y) {
			return (Math.min(x, y));
		}
//	    Make a utility function to calculate middle index
		static int getMid(int s,int e) {
			return (s+(e-s)/2);
		}
	    static int RMQUtil(int ss,int se,int qs,int qe,int index) {
//	    	case of complete overlap
	    	if(qs<=ss && qe>=se) 
	    		return st[index];
	    	//if this segment is outside the given range
	    	if(qs>se || qe<ss)
	    		return Integer.MAX_VALUE;
//	    	Case of partial overlap
	    	int mid=getMid(ss,se);
	    	return minVal(RMQUtil(ss, mid, qs, qe, 2*index+1),RMQUtil(mid+1, se, qs, qe, 2*index+2));
	    }
	    static int RMQ(int n,int qs,int qe) {
	    	if(qs<0 || qs>qe || qe>n-1)
	    		return -1;
	    	return RMQUtil(0, n-1, qs, qe,0);
	    }
	    static int constructSTUtil(int 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]; 
	    } 
		static void constructST(int arr[],int n) {
//			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 int[max_size];
			constructSTUtil(arr,0,n-1,0);
		}
		  static void updateValueUtil(int ss, int se, int i, int diff, int si) { 
        // Base Case: If the input index lies outside the range of  
        // this segment 
        if (i < ss || i > se) 
            return; 
  
        // If the input index is in range of this node, then update the 
        // value of the node and its children 
        st[si] = st[si] + diff; 
        if (se != ss) { 
            int mid = getMid(ss, se); 
            updateValueUtil(ss, mid, i, diff, 2 * si + 1); 
            updateValueUtil(mid + 1, se, i, diff, 2 * si + 2); 
        } 
    } 
  
    // The function to update a value in input array and segment tree. 
   // It uses updateValueUtil() to update the value in segment tree 
      static void updateValue(int arr[], int n, int i, int new_val) { 
        // Check for erroneous input index 
        if (i < 0 || i > n - 1) { 
            System.out.println("Invalid Input"); 
            return; 
        } 
  
        // Get the difference between new value and old value 
        int diff = new_val - arr[i]; 
  
        // Update the value in array 
        arr[i] = new_val; 
  
        // Update the values of nodes in segment tree 
        updateValueUtil(0, n - 1, i, diff, 0); 
    } 
      static long modexpo(long x,long n,long m){
        if(n==0)
            return 1;
        else if(n%2==0)
            return (modexpo(((x%m)*(x%m))%m,n/2,m))%m;
        else
            return ((x%m)*((modexpo(((x%m)*(x%m))%m,(n-1)/2,m))%m))%m;
      } 
       static int gcd(int a,int b){
           if(b==0)
              return a;
           else 
              return gcd(b,a%b);
       }
       static long gcd(long a,long b){
           if(b==0)
              return a;
           else 
              return gcd(b,a%b);
       }
	 static class FastReader{
          BufferedReader in;
          StringTokenizer st;
          public FastReader(){
              in=new BufferedReader(new InputStreamReader(System.in));
          }
          String next(){
              while(st==null || !st.hasMoreElements()){
                  try{
                      st=new StringTokenizer(in.readLine());
                  }
                  catch(IOException e){
                      e.printStackTrace();
                  }
               }
               return st.nextToken();
            }
            int nextInt(){
                return Integer.parseInt(next());
            }
            long nextLong(){
                return Long.parseLong(next());
            }
            double nextDouble(){
                return Double.parseDouble(next());
            }
            String nextLine(){
            String str19 = "";
            try{
                str19 = in.readLine();
            }
            catch (IOException e){
                e.printStackTrace();
             }
            return str19;
        }
      }    
}
