Problem:
Score : 400 points

Problem Statement

You are given positive integers N and M.

How many sequences a of length N consisting of positive integers satisfy a_1 \times a_2 \times ... \times a_N = M? Find the count modulo 10^9+7.

Here, two sequences a' and a'' are considered different when there exists some i such that a_i' \neq a_i''.

Constraints

All values in input are integers.

1 \leq N \leq 10^5

1 \leq M \leq 10^9

Input

Input is given from Standard Input in the following format:

N M

Output

Print the number of the sequences consisting of positive integers that satisfy the condition, modulo 10^9 + 7.

Sample Input 1

2 6

Sample Output 1

4

Four sequences satisfy the condition: \{a_1, a_2\} = \{1, 6\}, \{2, 3\}, \{3, 2\} and \{6, 1\}.

Sample Input 2

3 12

Sample Output 2

18

Sample Input 3

100000 1000000000

Sample Output 3

957870001

Solution in C (GCC 5.4.1) (judge verdict: Time Limit Exceeded)

#include <stdio.h>
#include <stdlib.h>
#include <math.h>


#define LIMIT 1000000007

typedef enum {false, true} bool;


int main(void)
{
    int N, M;
    int i, j, k;
    int *factor;  // related to factor_ctr
    int factor_ctr;
    int *factor_num;  // related to factor_ctr
    bool **factor_matrix;  // factor_ctr x factor_ctr
    int ctr, ctr_bk;
    long long sum;
    long long *iterative_array;  // related to factor_ctr
    long long **diff_array;  // related to factor_ctr
    bool *flag_incremental, *flag_iterative;
    int diff_ctr;
    long long iterative_incremental;
    long long *iterative_incremental2;
    
    scanf("%d %d", &N, &M);
    
    /**/
    
    factor_ctr = 0;
    
    
    for(i=1; i<(int)sqrt(M); i++)
    {
        if(M%i == 0)
        {
            factor_ctr += 2;
        }
    }
    
    if(M%i == 0)
    {
        if(M == i*i)
            factor_ctr++;
        else
            factor_ctr += 2;
    }
    //printf("factor_ctr: %d\n", factor_ctr);
    
    
    factor = (int*)malloc(sizeof(int)*factor_ctr);
    factor_num = (int*)malloc(sizeof(int)*factor_ctr);
    
    factor_matrix = (bool**)malloc(sizeof(bool*)*factor_ctr);
    for(i=0; i<factor_ctr; i++)
        factor_matrix[i] = (bool*)malloc(sizeof(bool)*factor_ctr);
    
    
    for(i=0; i<factor_ctr; i++)
    {
        factor_num[i] = 0;
    }
    
    ctr = 0;
    ctr_bk = factor_ctr;
    
    for(i=1; i<(int)sqrt(M); i++)
    {
        if(M%i == 0)
        {
            factor[ctr++] = i;
            //printf("%d  ", i);
            factor[--ctr_bk] = M/i;
            //printf("%d\n", M/i);
        }
    }
    //system("pause");
    
    if(M%i == 0)
    {
        if(M == i*i)
        {
            factor[ctr] = i;
            //printf("%d\n", i);
        }
        else
        {
            factor[ctr] = i;
            //printf("%d  ", i);
            factor[--ctr_bk] = M/i;
            //printf("%d\n", M/i);
        }
    }
    
    /**/
    
    for(i=0; i<factor_ctr; i++)
    {
        for(j=0; j<=i; j++)
        {
            if(factor[i]%factor[j] == 0)
                factor_num[i]++;
        }
        //printf("factor_num[%d]: %d\n", i, factor_num[i]);
    }
    //system("pause");
    
    /**/
    
    for(i=0; i<factor_ctr; i++)
    {
        //printf("factor_matrix[%d][]:\n", i);
        
        for(j=0; j<=i; j++)
        {
            factor_matrix[i][j] = false;
            
            //printf("%d ", factor_matrix[i][j]);
        }
        
        for(; j<factor_ctr; j++)
        {
            if(factor[j]%factor[i] == 0)
                factor_matrix[i][j] = true;
            else
                factor_matrix[i][j] = false;
            
            //printf("%d ", factor_matrix[i][j]);
        }
        //printf("\n");
    }
    //system("pause");
    
    /**/
    
    iterative_array = (long long*)malloc(sizeof(long long)*factor_ctr);
    
    diff_array = (long long**)malloc(sizeof(long long*)*factor_ctr);
    for(i=0; i<factor_ctr; i++)
        diff_array[i] = (long long*)malloc(sizeof(long long)*2);
    
    flag_incremental = (bool*)malloc(sizeof(bool)*factor_ctr);
    flag_iterative = (bool*)malloc(sizeof(bool)*factor_ctr);
    
    iterative_incremental2 = (long long*)malloc(sizeof(long long)*factor_ctr);
    
    
    for(i=0; i<factor_ctr-1; i++)
    {
        iterative_array[i] = 0;
    }
    iterative_array[i] = 1;
    
    
    if(N == 1)
        printf("1\n");
    else if(N == 2)
    {
        printf("%d\n", factor_num[factor_ctr-1]);
    }
    else
    {
        for(i=factor_ctr-1; i>=0; i--)
        {
            diff_array[i][0] = 0;
            diff_array[i][1] = 0;
            
            flag_incremental[i] = false;
            flag_iterative[i] = false;
            
            diff_ctr = 0;
            
                
            for(j=i+1; j<factor_ctr-1; j++)
            {
                if(factor_matrix[i][j])
                {
                    if(flag_incremental[j])
                    {
                        flag_incremental[i] = true;
                        flag_iterative[i] = true;
                        
                        break;
                    }
                    else
                    {
                        if(diff_array[j][0] != 0)
                        {
                            flag_incremental[i] = true;
                        
                            diff_array[i][0] += diff_array[j][0];
                            diff_array[i][1] += diff_array[j][1];
                        }
                        else
                        {
                            diff_ctr++;
                        }
                    }
                }
            }
            
            if(!flag_incremental[i])
            {
                diff_array[i][0] = diff_ctr;
                diff_array[i][1] = 1;
            }
            else
            {
                diff_array[i][1] += diff_ctr;
            }
        }
        
        
        for(j=0; j<N-2; j++)
        {
        for(i=0; i<factor_ctr-1; i++)
        {
            //printf("i: %d; (%lld, %lld)\n", i+1, diff_array[i][0], diff_array[i][1]);
            //printf("%d\n", flag_incremental[i]);
            
            
            
            if(flag_incremental[i])
            {
                if(flag_iterative[i])
                {
                for(k=i+1; k<factor_ctr; k++)
                    if(factor_matrix[i][k])
                        iterative_array[i] = (iterative_array[i]+iterative_array[k])%LIMIT;
                
                }
                else
                {
                    if(j == 0)
                    {
                        iterative_array[i] = 1;
                        iterative_incremental2[i] = 1;
                    }
                    else
                    {
                        iterative_incremental2[i] = (iterative_incremental2[i]+diff_array[i][0]*(j-1)+diff_array[i][1])%LIMIT;
                        iterative_array[i] = (iterative_array[i]+iterative_incremental2[i])%LIMIT;
                    }
                }
                //iterative_array[i] = 1;
                //iterative_incremental = 1;
                
                /*for(j=0; j<N-3; j++)
                {
                    iterative_incremental = (iterative_incremental+diff_array[i][0]*j+diff_array[i][1])%LIMIT;
                    iterative_array[i] = (iterative_array[i]+iterative_incremental)%LIMIT;
                }*/
            }
            else
            {
                //for(j=0; j<N-2; j++)
                //{
                    iterative_array[i] = (iterative_array[i]+diff_array[i][0]*j+diff_array[i][1])%LIMIT;
                //}
            }
        }
        }
        //system("pause");
        
        
        sum = 0;
        
        for(i=0; i<factor_ctr; i++)
        {
            sum = (sum+iterative_array[i]*factor_num[i])%LIMIT;
            //printf("iterative_array[%d]: %lld\n", i, iterative_array[i]);
        }
        
        printf("%lld\n", sum);
    }
    
    
    free(factor);
    free(factor_num);
    
    for(i=0; i<factor_ctr; i++)
        free(factor_matrix[i]);
    free(factor_matrix);
    
    free(iterative_array);
    
    for(i=0; i<factor_ctr; i++)
        free(diff_array[i]);
    free(diff_array);
    
    free(flag_incremental);
    free(flag_iterative);
    free(iterative_incremental2);
    
    //system("pause");
    
    return 0;
}