Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Problem E
Bringing Order to Disorder

A sequence of digits usually represents a number, but we may define an alternative interpretation. In this problem we define a new interpretation with the order relation $\prec$ among the digit sequences of the same length defined below.

Let $s$ be a sequence of $n$ digits, $d_1d_2 ... d_n$, where each $d_i$ $(1 \leq i \leq n)$ is one of 0, 1, ... , and 9. Let sum($s$), prod($s$), and int($s$) be as follows:

sum($s$) = $d_1 + d_2 + ... + d_n$

prod($s$) = $(d_1 + 1) \times (d_2 + 1) \times ... \times (d_n + 1)$

int($s$) = $d_1 \times 10^{n-1} + d_2 \times 10^{n-2} + ... + d_n \times 10^0$

int($s$) is the integer the digit sequence $s$ represents with normal decimal interpretation.

Let $s_1$ and $s_2$ be sequences of the same number of digits. Then $s_1 \prec s_2$ ($s_1$ is less than $s_2$) is satisfied if and only if one of the following conditions is satisfied.

sum($s_1$) $<$ sum($s_2$)

sum($s_1$) $=$ sum($s_2$) and prod($s_1$) $<$ prod($s_2$)

sum($s_1$) $=$ sum($s_2$), prod($s_1$) $=$ prod($s_2$), and int($s_1$) $<$ int($s_2$)

For 2-digit sequences, for instance, the following relations are satisfied.

$00 \prec 01 \prec 10 \prec 02 \prec 20 \prec 11 \prec 03 \prec 30 \prec 12 \prec 21 \prec ... \prec 89 \prec 98 \prec 99$

Your task is, given an $n$-digit sequence $s$, to count up the number of $n$-digit sequences that are less than $s$ in the order $\prec$ defined above.

Input

The input consists of a single test case in a line.

$d_1d_2 ... d_n$

$n$ is a positive integer at most 14. Each of $d_1, d_2, ...,$ and $d_n$ is a digit.

Output

Print the number of the $n$-digit sequences less than $d_1d_2 ... d_n$ in the order defined above.

Sample Input 1

20

Sample Output 1

4

Sample Input 2

020

Sample Output 2

5

Sample Input 3

118

Sample Output 3

245

Sample Input 4

11111111111111

Sample Output 4

40073759

Sample Input 5

99777222222211

Sample Output 5

23733362467675

Solution in C++11 (judge verdict: Accepted)

#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const long long INF = (long long) 1e16;

//int d[15][127][43][29][15],;
int g[20][5], f[20];
char str[20];
short d[15][127][43][29][15];
long long p[43][29][15][15], ways[20][200], comb[20][20];
vector < vector <long long> > dp[15][43][29][15];

long long mul(long long x, long long y) {
    return min(x * y, INF);
}

int main() {

    for (int i = 1; i <= 10; i++) {
        for (int j = 0; j < 4; j++) {
            g[i][j] = 0;
        }
        int x = i;
        while (x % 2 == 0) {
            g[i][0]++;
            x /= 2;
        }
        while (x % 3 == 0) {
            g[i][1]++;
            x /= 3;
        }
        while (x % 5 == 0) {
            g[i][2]++;
            x /= 5;
        }
        while (x % 7 == 0) {
            g[i][3]++;
            x /= 7;
        }
    }

    p[0][0][0][0] = 1;

    for (int i = 0; i <= 42; i++) {
        for (int j = 0; j <= 28; j++) {
            for (int k = 0; k <= 14; k++) {
                for (int l = 0; l <= 14; l++) {
                    if (i != 0) {
                        p[i][j][k][l] = mul(p[i - 1][j][k][l], 2LL);
                    } else if (j != 0) {
                        p[i][j][k][l] = mul(p[i][j - 1][k][l], 3LL);
                    } else if (k != 0) {
                        p[i][j][k][l] = mul(p[i][j][k - 1][l], 5LL);
                    } else if (l != 0) {
                        p[i][j][k][l] = mul(p[i][j][k][l - 1], 7LL);
                    }
                }
            }
        }
    }

    memset(d, -1, sizeof d);

    d[0][0][0][0][0] = 0;

    for (int i = 0; i < 14; i++) {
        for (int s = 0; s <= 126; s++) {
            for (int x = 0; x <= 42; x++) {
                for (int y = 0; y <= 28; y++) {
                    for (int z = 0; z <= 14; z++) {
                        if (d[i][s][x][y][z] == -1) {
                            continue;
                        }
                        for (int dig = 1; dig <= 10; dig++) {
                            int ns = s + dig - 1;
                            int nx = x + g[dig][0];
                            int ny = y + g[dig][1];
                            int nz = z + g[dig][2];
                            int now = d[i][s][x][y][z] + g[dig][3];
                            d[i + 1][ns][nx][ny][nz] = max(d[i + 1][ns][nx][ny][nz], short(now));
                        }
                    }
                }
            }
        }
    }

    for (int i = 0; i <= 14; i++) {
        for (int j = 0; j <= 42; j++) {
            for (int k = 0; k <= 28; k++) {
                for (int l = 0; l <= 14; l++) {
                    for (int s = 126; s >= 0; s--) {
                        if (d[i][s][j][k][l] != -1) {
                            dp[i][j][k][l] = vector < vector <long long> > (s + 1, vector <long long>());
                            break;
                        }
                    }
                }
            }
        }
    }

    for (int i = 0; i <= 14; i++) {
        for (int x = 0; x <= 42; x++) {
            for (int y = 0; y <= 28; y++) {
                for (int z = 0; z <= 14; z++) {
                    for (int s = 0; s < dp[i][x][y][z].size(); s++) {
                        if (d[i][s][x][y][z] == -1) {
                            continue;
                        }
                        int l = d[i][s][x][y][z] + 1;
                        dp[i][x][y][z][s] = vector <long long> (l, 0);
                    }
                }
            }
        }
    }

    dp[0][0][0][0][0][0] = 1;

    memset(ways, 0, sizeof ways);

    for (int i = 0; i < 14; i++) {
        for (int x = 0; x <= 42; x++) {
            for (int y = 0; y <= 28; y++) {
                for (int z = 0; z <= 14; z++) {
                    for (int s = 0; s < dp[i][x][y][z].size(); s++) {
                        for (int w = 0; w < dp[i][x][y][z][s].size(); w++) {
                            if (dp[i][x][y][z][s][w] == 0) {
                                continue;
                            }
                            long long val = dp[i][x][y][z][s][w];
                            for (int dig = 1; dig <= 10; dig++) {
                                int ns = s + dig - 1;
                                int nx = x + g[dig][0];
                                int ny = y + g[dig][1];
                                int nz = z + g[dig][2];
                                int nw = w + g[dig][3];
                                ways[i + 1][ns] += val;
                                dp[i + 1][nx][ny][nz][ns][nw] += val;
                            }
                        }
                    }
                }
            }
        }
    }

    memset(comb, 0, sizeof comb);

    for (int i = 0; i <= 15; i++) {
        comb[i][0] = 1;
        for (int j = 1; j <= i; j++) {
            comb[i][j] = comb[i - 1][j - 1] + comb[i - 1][j];
        }
    }

    for (int t = 1; scanf("%s", str) != EOF; t++) {
        int n = strlen(str);
        int sum = 0;
        long long res = 0;
        long long prod = 1;
        for (int i = 0; i < n; i++) {
            sum += str[i] - '0';
            prod *= (str[i] - '0' + 1);
        }
        for (int i = 0; i < sum; i++) {
            res += ways[n][i];
        }
        for (int x = 0; x <= 42; x++) {
            for (int y = 0; y <= 28; y++) {
                for (int z = 0; z <= 14; z++) {
                    if (sum >= dp[n][x][y][z].size()) {
                        continue;
                    }
                    for (int w = 0; w < dp[n][x][y][z][sum].size(); w++) {
                        if (p[x][y][z][w] < prod) {
                            res += dp[n][x][y][z][sum][w];
                        }
                    }
                }
            }
        }
        for (int i = 0; i < 4; i++) {
            f[i] = 0;
        }
        for (int i = 0; i < n; i++) {
            int dig = str[i] - '0' + 1;
            for (int j = 0; j < 4; j++) {
                f[j] += g[dig][j];
            }
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j <= 9; j++) {
                if (j >= str[i] - '0') {
                    break;
                }
                int x = 0;
                int y = 0;
                int z = 0;
                int w = 0;
                int s = 0;
                for (int k = 0; k < i; k++) {
                    int dig = str[k] - '0' + 1;
                    s += dig - 1;
                    x += g[dig][0];
                    y += g[dig][1];
                    z += g[dig][2];
                    w += g[dig][3];
                }
                s += j;
                x += g[j + 1][0];
                y += g[j + 1][1];
                z += g[j + 1][2];
                w += g[j + 1][3];
                int ns = sum - s;
                int nx = f[0] - x;
                int ny = f[1] - y;
                int nz = f[2] - z;
                int nw = f[3] - w;
                if (ns < 0 || nx < 0 || ny < 0 || nz < 0 || nw < 0) {
                    continue;
                }
                if (ns >= dp[n - i - 1][nx][ny][nz].size()) {
                    continue;
                }
                if (nw >= dp[n - i - 1][nx][ny][nz][ns].size()) {
                    continue;
                }
                res += dp[n - i - 1][nx][ny][nz][ns][nw];
            }
        }
        printf("%lld\n", res);
    }

    return 0;

}