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: Runtime Error)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h> // uint64_t
#include <math.h>

#define max(a,b) ((a) > (b) ? (a) : (b))
#define min(a,b) ((a) > (b) ? (b) : (a))
#define BUF_SIZE 30

// size: specify sizeof(str)
int get_str(char *str, int size) {
    if(!fgets(str, size, stdin)) return -1;
    return 0;
}

int get_int(void) {
  int num;
#ifdef BUF_SIZE
  char line[BUF_SIZE];
  if(!fgets(line, BUF_SIZE, stdin)) return 0;
  sscanf(line, "%d", &num);
#else
#error
#endif
  return num;
}

int get_int2(int *a1, int *a2) {
#ifdef BUF_SIZE
  char line[BUF_SIZE];
  if(!fgets(line, BUF_SIZE, stdin)) return -1;
  sscanf(line, "%d %d", a1, a2);
#else
#error
#endif
  return 0;
}

#define POWER_MAX 20
#define CNT_MAX 2000

int asc(const void *a1, const void *a2) {
    return *(int*)a1 - *(int*)a2;
}

#define DIVISOR 1000000007

struct pair {
    int p1;
    int p2;
};

int find_other(int *divisors, int size, int sum_idx, int p1_idx) {
    int i;
    int s = divisors[sum_idx];
    int other = s/divisors[p1_idx];
    // find idx
    for(i = 1; i <= sum_idx; i++) {
        if(divisors[i] == other) return i;
    }
    return -1;
}

int main(void) {
    int len, orig;
    static uint64_t dp[POWER_MAX][CNT_MAX];
    int i, j;
    get_int2(&len, &orig);
    int orig_2 = (int)sqrt(0.5 + orig);

    // get divisor
    static int divs[CNT_MAX];
    int didx = 1; // 1-indexed
    for(i = 1; i <= orig_2; i++) {
        if(orig%i) continue;
        divs[didx++] = i;
        divs[didx++] = (orig/i);
    }
    // max: divs[didx-1] = orig
    qsort(divs, didx, sizeof(int), asc);
    // initialization
    for(i = 1; i < didx; i++) dp[0][i] = 1;

    int power;
    for(power = 1; power < POWER_MAX; power++) {
        // assume that didx < CNT_MAX
        for(i = 1; i <= didx-1; i++) {
            int d = divs[i];
            uint64_t res = 0;
            for(j = i; j >= 1; j--) {
                if(d % divs[j]) continue;
                int k = find_other(divs, didx, i, j);
                res = (res + dp[power-1][j] * dp[power-1][k])%DIVISOR;
            }
            dp[power][i] = res;
        }
#ifdef DEBUG
        printf("dp[%d][%d] = %llu\n", power, didx-1, dp[power][didx-1]);
#endif
    }

    static uint64_t dp2[POWER_MAX][CNT_MAX];
    int first = 1;
    for(power = 0; power < POWER_MAX; power++) {
        int flag = !!(len & (1<<power));
        if(first && flag) {
            for(i = 1; i <= didx-1; i++) dp2[power][i] = dp[power][i];
            first = 0;
            continue;
        }
        // take over the previous status
        if(!flag) {
            for(i = 1; i <= didx-1; i++) dp2[power][i] = dp2[power-1][i];
            continue;
        }
        //if(!(len & (1<<power))) continue;
        for(i = 1; i <= didx-1; i++) {
            int d = divs[i];
            uint64_t res = 0;
            for(j = i; j >= 1; j--) {
                if(d % divs[j]) continue;
                int k = find_other(divs, didx, i, j);
                res = (res + dp2[power-1][j] * dp[power][k])%DIVISOR;
            }
            dp2[power][i] = res;
        }
#ifdef DEBUG
        printf("dp2[%d][%d] = %llu\n", power, didx-1, dp[power][didx-1]);
#endif
    }
    printf("%d\n", (int)dp2[POWER_MAX-1][didx-1]);
    return 0;
}