This night wasn't easy on Vasya. His favorite team lost, and he didn't find himself victorious either — although he played perfectly, his teammates let him down every time. He had to win at least one more time, but the losestreak only grew longer and longer... It's no wonder he didn't get any sleep this night at all.

In the morning, Vasya was waiting the bus to the university on the bus stop. Vasya's thoughts were hazy and so he couldn't remember the right bus' number quite right and got onto the bus with the number n.

In the bus, Vasya thought that he could get the order of the digits in the number of the bus wrong. Futhermore, he could "see" some digits several times, but the digits he saw were definitely in the real number of the bus. For example, if Vasya saw the number 2028, it could mean that the real bus number could be 2028, 8022, 2820 or just 820. However, numbers 80, 22208, 52 definitely couldn't be the number of the bus. Also, real bus number couldn't start with the digit 0, this meaning that, for example, number 082 couldn't be the real bus number too.

Given n, determine the total number of possible bus number variants.

Input

The first line contains one integer n (1 ≤ n ≤ 10^{18}) — the number of the bus that was seen by Vasya. It is guaranteed that this number does not start with 0.

Output

Output a single integer — the amount of possible variants of the real bus number.

Examples

Input

97


Output

2


Input

2028


Output

13

Note

In the first sample, only variants 97 and 79 are possible.

In the second sample, the variants (in the increasing order) are the following: 208, 280, 802, 820, 2028, 2082, 2208, 2280, 2802, 2820, 8022, 8202, 8220.
/*
 * Author Ayub Subhaniya
 * Institute DA-IICT
 */

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

public class CodeForces2 {

    InputStream in;
    PrintWriter out;

    long mod = (long) 1e9 + 7;
    int MAX = (int) 1e6 + 7;
    double eps = 1e-6;
    int MAXB=31;

    void solve() {
        String s=ns();
        int n=s.length();
        int cnt[]=new int[10];
        for (int i=0;i<n;i++)
            cnt[s.charAt(i)-'0']++;

        int MAXC=20;
        long C[][]=new long[MAXC][MAXC];
        for (int i=0;i<MAXC;i++){
            C[i][0]=C[i][i]=1;
        }

        for (int i=2;i<MAXC;i++)
            for (int j=1;j<i;j++){
                C[i][j]=C[i-1][j-1]+C[i-1][j];
            }

        long dp[][]=new long[11][n+1];
        dp[10][0]=1;
        for (int i=9;i>=0;i--){
            for (int j=0;j<=n;j++){
                if (cnt[i]==0)
                    dp[i][j]=dp[i+1][j];
                else {
                    for (int k=1;k<=cnt[i];k++){
                        if ((j-(i==0?1:0))>=k)
                            dp[i][j]+=C[j-(i==0?1:0)][k]*dp[i+1][j-k];
                    }
                }
            }
        }
        long sum=0;
        for (int i=0;i<=n;i++)
            sum+=dp[0][i];
        out.println(sum);
    }



    int dx[] = new int[]{1, -1, 0, 0};
    int dy[] = new int[]{0, 0, 1, -1};

    class Pair implements Comparable<Pair> {
        int x;
        int y;

        Pair(int a, int b) {
            x = a;
            y = b;
        }

        @Override
        public boolean equals(Object o) {
            Pair other = (Pair) o;
            return x == other.x && y == other.y;
        }

        public String toString() {
            return x + " " + y;
        }

        @Override
        public int compareTo(Pair o) {
            if (x == o.x)
                return Integer.compare(y, o.y);
            else
                return Integer.compare(x, o.x);
        }

        @Override
        public int hashCode() {
            return Objects.hash(x, y);
        }
    }


    class Point {
        double x;
        double y;
        double z;

        Point(double a, double b, double c) {
            z = c;
            x = a;
            y = b;
        }

        public String toString() {
            return x + " " + y + " " + z;
        }

        double mod() {
            double d = x * x + y * y + z * z;
            return d;
            //return Double.parseDouble(df.format(d));
        }

        Point dot(Point p) {
            return new Point(p.x * x, p.y * y, p.z * z);
        }

        Point substract(Point p) {
            return new Point(x - p.x, y - p.y, z - p.z);
        }

        Point cross(Point p) {
            double uvi, uvj, uvk;
            uvi = y * p.z - p.y * z;
            uvj = p.x * z - x * p.z;
            uvk = x * p.y - p.x * y;
            return new Point(uvi, uvj, uvk);
        }
    }

    long pow(long x, long n, long M) {
        x %= M;
        long result = 1;
        while (n > 0) {
            if (n % 2 == 1)
                result = (result * x) % M;
            x = (x * x) % M;
            n = n / 2;
        }
        return result;
    }

    long modInverse(long A, long M) {
        extendedEuclid(A, M);
        return (EEx % M + M) % M;
    }

    long EEd, EEx, EEy;

    void extendedEuclid(long A, long B) {
        if (B == 0) {
            EEd = A;
            EEx = 1;
            EEy = 0;
        } else {
            extendedEuclid(B, A % B);
            long temp = EEx;
            EEx = EEy;
            EEy = temp - (A / B) * EEy;
        }
    }

    int max(int a, int b) {
        if (a > b)
            return a;
        else
            return b;
    }

    int min(int a, int b) {
        if (a > b)
            return b;
        else
            return a;
    }

    long max(long a, long b) {
        if (a > b)
            return a;
        else
            return b;

    }


    long min(long a, long b) {
        if (a > b)
            return b;
        else
            return a;

    }

    long add(long a, long b) {
        long x = (a + b);
        while (x >= mod) x -= mod;
        return x;

    }


    long sub(long a, long b) {
        long x = (a - b);
        while (x < 0) x += mod;
        return x;

    }


    long mul(long a, long b) {
        a %= mod;
        b %= mod;
        long x = (a * b);
        return x % mod;

    }

    void run() throws Exception {
        String INPUT = "/Users/ayubsubhaniya/IdeaProjects/Test/src/input.txt";
        in = oj ? System.in : new FileInputStream(INPUT);
        out = new PrintWriter(System.out);

        long s = System.currentTimeMillis();
        solve();
        out.flush();
        tr(System.currentTimeMillis() - s + "ms");

    }

    public static void main(String[] args) throws Exception {

        new CodeForces2().run();
    }

    private byte[] inbuf = new byte[1024 * 1024];
    public int lenbuf = 0, ptrbuf = 0;

    private int readByte() {
        if (lenbuf == -1)
            throw new InputMismatchException();
        if (ptrbuf >= lenbuf) {
            ptrbuf = 0;
            try {
                lenbuf = in.read(inbuf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (lenbuf <= 0)
                return -1;
        }
        return inbuf[ptrbuf++];
    }

    private boolean inSpaceChar(int c) {
        return !(c >= 33 && c <= 126);
    }

    private int skip() {
        int b;
        while ((b = readByte()) != -1 && inSpaceChar(b))
            ;
        return b;
    }

    private double nd() {
        return Double.parseDouble(ns());
    }

    private char nc() {
        return (char) skip();
    }

    private String ns() {
        int b = skip();
        StringBuilder sb = new StringBuilder();
        while (!(inSpaceChar(b))) { // when nextLine, (inSpaceChar(b) && b != ' ')
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }

    private char[] ns(int n) {
        char[] buf = new char[n];
        int b = skip(), p = 0;
        while (p < n && !(inSpaceChar(b))) {
            buf[p++] = (char) b;
            b = readByte();
        }
        return n == p ? buf : Arrays.copyOf(buf, p);
    }

    private char[][] nm(int n, int m) {
        char[][] map = new char[n][];
        for (int i = 0; i < n; i++)
            map[i] = ns(m);
        return map;
    }

    private int[] na(int n) {
        int[] a = new int[n];
        for (int i = 0; i < n; i++)
            a[i] = ni();
        return a;
    }

    private int ni() {
        int num = 0, b;
        boolean minus = false;
        while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
            ;
        if (b == '-') {
            minus = true;
            b = readByte();
        }

        while (true) {
            if (b >= '0' && b <= '9') {
                num = num * 10 + (b - '0');
            } else {
                return minus ? -num : num;
            }
            b = readByte();
        }
    }

    private long nl() {
        long num = 0;
        int b;
        boolean minus = false;
        while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
            ;
        if (b == '-') {
            minus = true;
            b = readByte();
        }

        while (true) {
            if (b >= '0' && b <= '9') {
                num = num * 10 + (b - '0');
            } else {
                return minus ? -num : num;
            }
            b = readByte();
        }
    }

    private boolean oj = System.getProperty("ONLINE_JUDGE") != null;

    private void tr(Object... o) {
        if (!oj)
            System.out.println(Arrays.deepToString(o));
    }

}