//package round464;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.InputMismatchException;

public class F {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni(), K = ni();
		int[][] ts = new int[K][];
		long all = 0;
		for(int i = 0;i < K;i++){
			ts[i] = na(2);
			all += ts[i][1] - ts[i][0];
		}
		int[] dpe = new int[n+1];
		int[] dpo = new int[n+1];
		Arrays.fill(dpe, 99999999);
		Arrays.fill(dpo, 99999999);
		if(ts[0][0] > n){
			out.println("Hungry");
			return;
		}
		dpe[ts[0][0]] = 0;
		for(int i = 0;i < K;i++){
			int[] ndpo = new int[n+1];
			int[] ndpe = new int[n+1];
			Arrays.fill(ndpo, 99999999);
			Arrays.fill(ndpe, 99999999);
			Deque<Integer> dq = new ArrayDeque<>();
			int w = ts[i][1] - ts[i][0];
			for(int j = 0;j <= n;j++){
				while(dq.size() > 0 && dpe[dq.peekLast()] >= dpe[j]){
					dq.pollLast();
				}
				while(dq.size() > 0 && dq.peekFirst() < j-w)dq.pollFirst();
				dq.add(j);
				ndpo[j] = Math.min(ndpo[j], dpe[dq.peekFirst()] + 1);
				if(j+w <= n)ndpe[j+w] = Math.min(ndpe[j+w], dpe[j]);
			}
			dq.clear();
			for(int j = 0;j <= n;j++){
				while(dq.size() > 0 && dpo[dq.peekLast()] >= dpo[j]){
					dq.pollLast();
				}
				while(dq.size() > 0 && dq.peekFirst() < j-w)dq.pollFirst();
				dq.add(j);
				ndpe[j] = Math.min(ndpe[j], dpo[dq.peekFirst()] + 1);
				ndpo[j] = Math.min(ndpo[j], dpo[j]);
			}
			dpo = ndpo;
			dpe = ndpe;

			for(int j = 0;j <= n;j++){
				dpe[j] = Math.min(dpe[j], dpo[j] + 1);
				dpo[j] = Math.min(dpo[j], dpe[j] + 1);
			}

			int s = (i == K-1 ? 2*n : ts[i+1][0]) - ts[i][1];
			for(int j = n;j >= s;j--){
				dpe[j] = dpe[j-s];
			}
			for(int j = Math.min(n, s-1);j >= 0;j--)dpe[j] = 99999999;

		}
		int ans = Math.min(dpe[n], dpo[n]);
		if(ans >= 9999999){
			out.println("Hungry");
		}else{
			out.println("Full");
			out.println(ans);
		}
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		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 F().run(); }

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

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

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(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(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(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 && !(isSpaceChar(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)); }
}


//some updates in import stuff
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.Math.abs;
import java.util.*;
import java.io.*;
import java.math.*;

//key points learned
//max space ever that could be alloted in a program to pass in cf
//int[][] prefixSum = new int[201][200_005];   -> not a single array more!!!
//never allocate memory again again to such bigg array, it will give memory exceeded for sure
//believe in your fucking solution and keep improving it!!! (sometimes)

public class Main{

    static int mod = (int) (Math.pow(10, 9)+7);
	static final int dx[] = { -1, 0, 1, 0 }, dy[] = { 0, -1, 0, 1 };
	static final int[] dx8 = { -1, -1, -1, 0, 0, 1, 1, 1 }, dy8 = { -1, 0, 1, -1, 1, -1, 0, 1 };
	static final int[] dx9 = { -1, -1, -1, 0, 0, 0, 1, 1, 1 }, dy9 = { -1, 0, 1, -1, 0, 1, -1, 0, 1 };

	static final double eps = 1e-10;
	static List<Integer> primeNumbers = new ArrayList<>();
    public static void main(String[] args) {
        MyScanner sc = new MyScanner();
        out = new PrintWriter(new BufferedOutputStream(System.out));

        //code below
        String str = sc.nextLine();
        char[] inp = str.toCharArray();
        int n = str.length();

        //since i have the input ready bois
        //keep solving until, there is no until keep solving bruh!! (simple)
        String[] pos = {"00", "25", "50", "75"};
        int count = 0;

        if(inp.length == 1){
            if(inp[0] == '0' || inp[0] == 'X' || inp[0] == '_') count++;
        }else{

            for(String cstr : pos){
                int X = -1;

                int idx = 0;
                boolean possible = true;
                for(int i = n-2; i < n; i++){
                    char curr = inp[i];
                    char strcurr = cstr.charAt(idx);
                    idx++;

                    if(curr == '_') continue;
                    else if(curr == 'X'){
                        if(X == -1){
                            X = (strcurr - '0');
                        }else{
                            if(X != strcurr - '0'){
                                possible = false;
                                break;
                            }
                        }
                    }else{
                        if(curr != strcurr){
                            possible = false;
                            break;
                        }
                    }

                }

                if(!possible) continue; //don't increase the count simple

                //to handle one small edge case which was this
                if(str.length() == 2){
                    if(cstr.charAt(0) == '0') continue;
                    // System.out.println(cstr);
                    count++;
                    continue;
                }

                //now yaha tak question done hai boss for sure!! We have the required X and stuff and all
                //now make all possible outcomes for X
                //if X == -1 && X == 0 else what else we can do?? - think about it for sure
                //if X is fixed , then simple
                //if X is zero then also simple
                //if X is not fixed, and X is not zero
                //make temp inp
                char[] ninp = Arrays.copyOf(inp, str.length());

                int cntX = 0;
                for(char ch : inp){
                    if(ch == 'X') cntX++;
                }

                if(X != -1 || cntX == 0){
                    if(X != -1){
                        for(int k = 0; k < str.length(); k++){
                            ninp[k] = inp[k] == 'X' ? (char)(X + '0') : inp[k];
                        }
                    }

                    if(ninp[0] == '0') continue;
                    int counter = 1;
                    for(int k = 0; k < str.length() - 2; k++){
                        if(ninp[k] == '_'){
                            if(k == 0){
                                counter = counter * 9;
                            }else{
                                counter = counter * 10;
                            }
                        }
                    }

                    count += counter;
                }else{

                    if(ninp[0] == '0') continue;  //simimlar to before

                    //now either 'X' or '_' or
                    int counter = 1;
                    for(int k = 0; k < str.length() - 2; k++){
                        if(ninp[k] == '_'){
                            if(k == 0){
                                counter = counter * 9;
                            }else{
                                counter = counter * 10;
                            }
                        }
                    }

                    //after this it is pretty simple, multiply X also
                    if(ninp[0] == 'X'){
                        counter = counter * 9;
                    }else{
                        counter = counter * 10;
                    }

                    count += counter;
                }
            }
        }

        System.out.println(count);

        out.close();
    }

    //new stuff to learn (whenever this is need for them, then only)
    //Lazy Segment Trees
    //Persistent Segment Trees
    //Square Root Decomposition
    //Geometry & Convex Hull
    //High Level DP -- yk yk
    //String Matching Algorithms
    //Heavy light Decomposition

    //Updation Required
    //Fenwick Tree - both are done (sum)
    //Segment Tree - both are done (min, max, sum)

    //-----CURRENTLY PRESENT-------//
    //Graph
    //DSU
    //powerMODe
    //power
    //Segment Tree (work on this one)
    //Prime Sieve
    //Count Divisors
    //Next Permutation
    //Get NCR
    //isVowel
    //Sort (int)
    //Sort (long)
    //Binomial Coefficient
    //Pair
    //Triplet
    //lcm (int & long)
    //gcd (int & long)
    //gcd (for binomial coefficient)
    //swap (int & char)
    //reverse
    //primeExponentCounts

    //Fast input and output

    //-------------------------------------------------------------------
    //-------------------------------------------------------------------
    //-------------------------------------------------------------------
    //-------------------------------------------------------------------
    //-------------------------------------------------------------------

    //GRAPH (basic structure)
    public static class Graph{
        public int V;
        public ArrayList<ArrayList<Integer>> edges;

        //2 -> [0,1,2] (current)
        Graph(int V){
            this.V  = V;
            edges = new ArrayList<>(V+1);
            for(int i= 0; i <= V; i++){
                edges.add(new ArrayList<>());
            }
        }

        public void addEdge(int from , int to){
            edges.get(from).add(to);
            edges.get(to).add(from);
        }
    }

    //DSU (path and rank optimised)
    public static class DisjointUnionSets {
        int[] rank, parent;
        int n;

        public DisjointUnionSets(int n)
        {
            rank = new int[n];
            parent = new int[n];
            Arrays.fill(rank, 1);
            Arrays.fill(parent,-1);
            this.n = n;
        }

        public int find(int curr){
            if(parent[curr] == -1)
                return curr;

            //path compression optimisation
            return parent[curr] = find(parent[curr]);
        }

        public void union(int a, int b){
            int s1 = find(a);
            int s2 = find(b);

            if(s1 != s2){
                //union by size
                if(rank[s1] < rank[s2]){
                    parent[s1] = s2;
                    rank[s2] += rank[s1];
                }else{
                    parent[s2] = s1;
                    rank[s1] += rank[s2];
                }
            }
        }
    }

    //with mod
    public static long powerMOD(long x, long y)
    {
        long res = 1L;
        while (y > 0)
        {
            // If y is odd, multiply x with result
            if ((y & 1) != 0){
                x %= mod;
                res %= mod;
                res = (res * x)%mod;
            }
            // y must be even now
            y = y >> 1; // y = y/2
            x%= mod;
            x = (x * x)%mod;  // Change x to x^2
        }
        return res%mod;
    }

    //without mod
    public static long power(long x, long y)
    {
        long res = 1L;
        while (y > 0)
        {
            // If y is odd, multiply x with result
            if ((y & 1) != 0){
                res = (res * x);
            }
            // y must be even now
            y = y >> 1; // y = y/
            x = (x * x);
        }
        return res;
    }

    public static class segmentTree{

        //so let's make a constructor function for this bad boi for sure!!!
        public long[] arr;
        public long[] tree;

        //COMPLEXITY (normal segment tree, stuff)
        //build -> O(n)
        //query -> O(logn)
        //update -> O(logn)
        //update-range -> O(n) (worst case)

        //simple iteration and stuff for sure
        public segmentTree(long[] arr){
            int n = arr.length;
            this.arr = new long[n];
            for(int i= 0; i < n; i++){
                this.arr[i] = arr[i];
            }

            tree = new long[4*n + 1];
        }

        //pretty basic idea if you read the code once
        //first make child node once
        //then form the parent node using them
        public void buildTree(int s, int e, int index){
            if(s == e){
                tree[index] = arr[s];
                return;
            }

            //recursive case
            int mid = (s + e)/2;
            buildTree(s, mid, 2 * index);
            buildTree(mid + 1, e, 2*index + 1);

            //the condition we want from children be like this
            tree[index] = min(tree[2 * index], tree[2 * index + 1]);
            return;
        }

        //definitely index based 0 query!!!
        //only int index = 1!!
        //baaki everything is simple as fuck
        public long query(int s, int e, int qs , int qe, int index){
            //complete overlap
            if(s >= qs && e <= qe){
                return tree[index];
            }

            //no overlap
            if(qe < s || qs > e){
                return Long.MAX_VALUE;
            }

            //partial overlap
            int mid = (s + e)/2;
            long left = query( s, mid , qs, qe, 2*index);
            long right = query( mid + 1, e, qs, qe, 2*index + 1);

            return min(left, right);
        }

        //updates are pretty cool
        //point update and range update!!!
        public void updateNode(int s, int e, int i, long increment, int index){

            //case where I is out of bounds
            if(i < s || i > e){
                return;
            }

            if(s == e){
                //making increment
                tree[index] += increment;
                return;
            }

            //otherwise
            int mid = (s + e)/2;
            updateNode(s, mid, i, increment, 2 * index);
            updateNode(mid + 1, e, i, increment, 2 * index + 1);

            tree[index] = min(tree[2 * index], tree[2 * index + 1]);
            return;
        }

        //gonna do range updates for sure now!!
        //let's do this bois!!! (solve this problem for sure)
        public void updateRange(int s, int e, int l, int r, long increment, int index){

            //out of bounds
            if(l > e || r < s){
                return;
            }

            //leaf node
            if(s == e){
                tree[index] += increment;
            }

            //recursive case
            int mid = (s + e)/2;
            updateRange(s, mid, l, r, increment, 2 * index);
            updateRange(mid + 1, e, l, r, increment, 2 * index);

            tree[index] = min(tree[2 * index], tree[2 * index + 1]);
        }

    }

    //prime sieve
    public static void primeSieve(int n){
        BitSet bitset = new BitSet(n+1);
        for(long i = 0; i < n ; i++){
            if (i == 0 || i == 1) {
                bitset.set((int) i);
                continue;
            }
            if(bitset.get((int) i)) continue;
            primeNumbers.add((int)i);
            for(long j = i; j <= n ; j+= i)
                bitset.set((int)j);
        }
    }

    //number of divisors
    public static int countDivisors(long number){
        if(number == 1) return 1;
        List<Integer> primeFactors = new ArrayList<>();
        int index = 0;
        long curr = primeNumbers.get(index);
        while(curr * curr <= number){
            while(number % curr == 0){
                number = number/curr;
                primeFactors.add((int) curr);
            }
            index++;
            curr = primeNumbers.get(index);
        }

        if(number != 1) primeFactors.add((int) number);
        int current = primeFactors.get(0);
        int totalDivisors = 1;
        int currentCount = 2;
        for (int i = 1; i < primeFactors.size(); i++) {
            if (primeFactors.get(i) == current) {
                currentCount++;
            } else {
                totalDivisors *= currentCount;
                currentCount = 2;
                current = primeFactors.get(i);
            }
        }
        totalDivisors *= currentCount;
        return totalDivisors;
    }

    //primeExponentCounts
    public static int primeExponentsCount(int n) {
        if (n <= 1)
            return 0;
        int sqrt = (int) Math.sqrt(n);
        int remainingNumber = n;
        int result = 0;
        for (int i = 2; i <= sqrt; i++) {
            while (remainingNumber % i == 0) {
                result++;
                remainingNumber /= i;
            }
        }
        //in case of prime numbers this would happen
        if (remainingNumber > 1) {
            result++;
        }
        return result;
    }

    //now adding next permutation function to java hehe
    public static boolean next_permutation(int[] p) {
        for (int a = p.length - 2; a >= 0; --a)
          if (p[a] < p[a + 1])
            for (int b = p.length - 1;; --b)
              if (p[b] > p[a]) {
                int t = p[a];
                p[a] = p[b];
                p[b] = t;
                for (++a, b = p.length - 1; a < b; ++a, --b) {
                  t = p[a];
                  p[a] = p[b];
                  p[b] = t;
                }
                return true;
              }
        return false;
    }

    //finding the value of NCR in O(RlogN) time and O(1) space
    public static long getNcR(int n, int r)
    {
        long p = 1, k = 1;
        if (n - r < r) r = n - r;

        if (r != 0) {
            while (r > 0) {
                p *= n;
                k *= r;
                long m = __gcd(p, k);
                p /= m;
                k /= m;
                n--;
                r--;
            }
        }
        else {
            p = 1;
        }
        return p;
    }

    //is vowel function
    public static boolean isVowel(char c)
    {
        return (c=='a' || c=='A' || c=='e' || c=='E' || c=='i' || c=='I' || c=='o' || c=='O' ||     c=='u' || c=='U');
    }

    //to sort the array with better method
	public static void sort(int[] a) {
		ArrayList<Integer> l=new ArrayList<>();
		for (int i:a) l.add(i);
		Collections.sort(l);
		for (int i=0; i<a.length; i++) a[i]=l.get(i);
	}

    //sort long
    public static void sort(long[] a) {
		ArrayList<Long> l=new ArrayList<>();
		for (long i:a) l.add(i);
		Collections.sort(l);
		for (int i=0; i<a.length; i++) a[i]=l.get(i);
	}

    //for calculating binomialCoeff
    public static int binomialCoeff(int n, int k)
    {
        int C[] = new int[k + 1];
        // nC0 is 1
        C[0] = 1;
        for (int i = 1; i <= n; i++) {
            // Compute next row of pascal
            // triangle using the previous row
            for (int j = Math.min(i, k); j > 0; j--)
                C[j] = C[j] + C[j - 1];
        }
        return C[k];
    }

    //Pair with int int
    public static class Pair{
        public int a;
        public int b;
        public int hashCode;

        Pair(int a , int b){
            this.a = a;
            this.b = b;
            this.hashCode = Objects.hash(a, b);
        }

        @Override
        public String toString(){
            return a + " -> " + b;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o)
                return true;
            if (o == null || getClass() != o.getClass())
                return false;
            Pair that = (Pair) o;
            return a == that.a && b == that.b;
        }

        @Override
        public int hashCode() {
            return this.hashCode;
        }
    }

    //Triplet with int int int
    public static class Triplet{

        public int a;
        public int b;
        public int c;

        Triplet(int a , int b, int c){
            this.a = a;
            this.b = b;
            this.c = c;
        }

        @Override
        public String toString(){
            return a + " -> " + b;
        }
    }

    //Shortcut function
    public static long lcm(long a , long b){
        return a * (b/gcd(a,b));
    }

    //let's make one for calculating lcm basically
    public static int lcm(int a , int b){
        return (a * b)/gcd(a,b);
    }

    //int version for gcd
    public static int gcd(int a, int b){
        if(b == 0)
            return a;

        return gcd(b , a%b);
    }

    //long version for gcd
    public static long gcd(long a, long b){
        if(b == 0)
            return a;

        return gcd(b , a%b);
    }

     //for ncr calculator(ignore this code)
     public static long __gcd(long n1, long n2)
     {
         long gcd = 1;
         for (int i = 1; i <= n1 && i <= n2; ++i) {
             // Checks if i is factor of both integers
             if (n1 % i == 0 && n2 % i == 0) {
                 gcd = i;
             }
         }
         return gcd;
     }

    //swapping two elements in an array
    public static void swap(int[] arr, int left , int right){
        int temp = arr[left];
        arr[left] = arr[right];
        arr[right] = temp;
    }

    //for char array
    public static void swap(char[] arr, int left , int right){
        char temp = arr[left];
        arr[left] = arr[right];
        arr[right] = temp;
    }

    //reversing an array
    public static void reverse(int[] arr){
        int left = 0;
        int right = arr.length-1;

        while(left <= right){
            swap(arr, left,right);
            left++;
            right--;
        }
    }

    public static long expo(long a, long b, long mod) {
        long res = 1;
        while (b > 0) {
            if ((b & 1) == 1L) res = (res * a) % mod;  //think about this one for a second
            a = (a * a) % mod;
            b = b >> 1;
        }
        return res;
    }

    //SOME EXTRA DOPE FUNCTIONS
    public static long mminvprime(long a, long b) {
        return expo(a, b - 2, b);
    }

    public static long mod_add(long a, long b, long m) {
        a = a % m;
        b = b % m;
        return (((a + b) % m) + m) % m;
    }

    public static long mod_sub(long a, long b, long m) {
        a = a % m;
        b = b % m;
        return (((a - b) % m) + m) % m;
    }

    public static long mod_mul(long a, long b, long m) {
        a = a % m;
        b = b % m;
        return (((a * b) % m) + m) % m;
    }

    public static long mod_div(long a, long b, long m) {
        a = a % m;
        b = b % m;
        return (mod_mul(a, mminvprime(b, m), m) + m) % m;
    }

    //O(n) every single time remember that
    public static long nCr(long N, long K , long mod){
        long upper = 1L;
        long lower = 1L;
        long lowerr = 1L;

        for(long i = 1; i <= N; i++){
            upper = mod_mul(upper, i, mod);
        }

        for(long i = 1; i <= K; i++){
            lower = mod_mul(lower, i, mod);
        }

        for(long i = 1; i <= (N - K); i++){
            lowerr = mod_mul(lowerr, i, mod);
        }

        // out.println(upper + " " + lower + " " + lowerr);
        long answer = mod_mul(lower, lowerr, mod);
        answer = mod_div(upper, answer, mod);

        return answer;
    }

    // long[] fact = new long[2 * n + 1];
    // long[] ifact = new long[2 * n + 1];
    // fact[0] = 1;
    // ifact[0] = 1;
    // for (long i = 1; i <= 2 * n; i++)
    // {
    //     fact[(int)i] = mod_mul(fact[(int)i - 1], i, mod);
    //     ifact[(int)i] = mminvprime(fact[(int)i], mod);
    // }
    //ifact is basically inverse factorial in here!!!!!(imp)
    public static long combination(long n, long r, long m, long[] fact, long[] ifact) {
        long val1 = fact[(int)n];
        long val2 = ifact[(int)(n - r)];
        long val3 = ifact[(int)r];
        return (((val1 * val2) % m) * val3) % m;
    }

    //-----------PrintWriter for faster output---------------------------------
    public static PrintWriter out;

    //-----------MyScanner class for faster input----------
    public static class MyScanner {
      BufferedReader br;
      StringTokenizer st;

        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.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 str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

    }
   //--------------------------------------------------------
}


import java.util.*;

public class Hello {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine().trim();
        assert str.length() >= 1 && str.length() <= 8 : "Length of S not in range";
        if (str.charAt(0) == '0') {
            System.out.println(str.length() > 1 ? "0" : "1");
            return;
        }
        int fromVal = Integer.parseInt("1" + "0".repeat(str.length() - 1));
        if (fromVal == 1) {
            fromVal = 0;
        } else if (fromVal == 10) {
            fromVal = 25;
        }
        int toVal = Integer.parseInt("9".repeat(str.length()));
        int count = 0;
        for (int val = fromVal; val <= toVal; val += 25) {
            if (canFormInteger(val, str)) {
                count++;
            }
        }
        System.out.println(count);
    }

    private static boolean canFormInteger(int num, String str) {
        String strNum = String.valueOf(num);
        char xVal = '*';
        for (int index = 0; index < str.length(); index++) {
            if (str.charAt(index) == '_') {
                continue;
            } else if (str.charAt(index) == 'X') {
                if (xVal != '*' && xVal != strNum.charAt(index)) {
                    return false;
                }
                xVal = strNum.charAt(index);
            } else if (str.charAt(index) != strNum.charAt(index)) {
                return false;
            }
        }
        return true;
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {

	static AReader scan = new AReader();
	static char[] cs;
	static int res = 0;
	static int X = 0;
	static int n;

	static void dfs(int u,int s){
		if(u >= n){
			if(s % 25 == 0) res++;
			return;
		}
		int t = cs[u] - '0';
		if(t>=0 && t <= 9) dfs(u+1,s*10+t);
		else if(cs[u] == 'X') dfs(u+1,s*10+X);
		else {
			if (u == n - 1) {
				dfs(u + 1, s * 10 + 5);
				dfs(u + 1, s * 10);
			} else {
				for (int i = 0; i < 10; i++) {
					if (i == 0 && u == 0) continue;
					dfs(u + 1, s * 10 + i);
				}
			}
		}
	}

	static void solve() {
		cs = scan.next().toCharArray();
		n = cs.length;
		boolean flag = false;
		for(char c:cs){
			if(c == 'X'){
				flag = true;
				break;
			}
		}
		if(cs[0] == '0' && n != 1){
			System.out.println(0);
			return;
		}
		if(flag){
		for(int i = 0;i<10;i++) {
			if(cs[0] == 'X' && n > 1 && i == 0) continue;
			X = i;
			dfs(0,0);
		}
		}else dfs(0,0);
		System.out.println(res);
	}

	public static void main(String[] args)  {
		//int T = scan.nextInt();
		//while (T-- > 0) {
		solve();
		//}
		//System.out.print(sb.toString());
	}
}

class AReader {
	private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
	private StringTokenizer tokenizer = new StringTokenizer("");

	private String innerNextLine() {
		try {
			return reader.readLine();
		} catch (IOException ex) {
			return null;
		}
	}

	public boolean hasNext() {
		while (!tokenizer.hasMoreTokens()) {
			String nextLine = innerNextLine();
			if (nextLine == null) {
				return false;
			}
			tokenizer = new StringTokenizer(nextLine);
		}
		return true;
	}

	public String nextLine() {
		tokenizer = new StringTokenizer("");
		return innerNextLine();
	}

	public String next() {
		hasNext();
		return tokenizer.nextToken();
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}
}

class Pair {
	int x,y;

	public Pair(int x, int y) {
		this.x = x;
		this.y = y;
	}
}


import java.util.*;

import java.io.*;
import java.math.*;
import java.sql.Array;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLIntegrityConstraintViolationException;

public class Main {
	 private static class MyScanner {
	        private static final int BUF_SIZE = 2048;
	        BufferedReader br;

	        private MyScanner() {
	            br = new BufferedReader(new InputStreamReader(System.in));
	        }

	        private boolean isSpace(char c) {
	            return c == '\n' || c == '\r' || c == ' ';
	        }

	        String next() {
	            try {
	                StringBuilder sb = new StringBuilder();
	                int r;
	                while ((r = br.read()) != -1 && isSpace((char)r));
	                if (r == -1) {
	                    return null;
	                }

	                sb.append((char) r);
	                while ((r = br.read()) != -1 && !isSpace((char)r)) {
	                    sb.append((char)r);
	                }
	                return sb.toString();
	            } catch (IOException e) {
	                e.printStackTrace();
	            }
	            return null;
	        }

	        int nextInt() {
	            return Integer.parseInt(next());
	        }

	        long nextLong() {
	            return Long.parseLong(next());
	        }

	        double nextDouble() {
	            return Double.parseDouble(next());
	        }
	    }
	  static class Reader{

			BufferedReader br;
			StringTokenizer st;
			public Reader() {
				br = new BufferedReader(new InputStreamReader(System.in));
			}
			String next()
		    {
		        while (st == null || !st.hasMoreElements())
		        {
		            try
		            {
		                st = new StringTokenizer(br.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 str = "";
		        try
		        {
		            str = br.readLine();
		        }
		        catch (IOException e)
		        {
		            e.printStackTrace();
		        }
		        return str;
		    }
		}

	  static long mod = (long)(1e9 + 7);

	static void sort(long[] arr ) {
		 ArrayList<Long> al = new ArrayList<>();
		 for(long e:arr) al.add(e);
		 Collections.sort(al);
		 for(int i = 0 ; i<al.size(); i++) arr[i] = al.get(i);
	 }
	static void sort(int[] arr ) {
		 ArrayList<Integer> al = new ArrayList<>();
		 for(int e:arr) al.add(e);
		 Collections.sort(al);
		 for(int i = 0 ; i<al.size(); i++) arr[i] = al.get(i);
	 }

	static void sort(char[] arr) {
		ArrayList<Character> al = new ArrayList<Character>();
		for(char cc:arr) al.add(cc);
		Collections.sort(al);
		for(int i = 0 ;i<arr.length ;i++) arr[i] = al.get(i);
	}

	static long mod_mul(  long... a) {
		long ans = a[0]%mod;
		for(int i = 1 ; i<a.length ; i++) {
			ans = (ans * (a[i]%mod))%mod;
		}

		return ans;
	}
	static long mod_sum( long... a) {
		long ans = 0;
		for(long e:a) {
			ans = (ans + e)%mod;
		}
		return ans;
	}
	 static long gcd(long a, long b)
	  {
	     if (b == 0)
	        return a;
	     return gcd(b, a % b);
	  }
	 static boolean[] prime(int num) {
			boolean[] bool = new boolean[num];

		      for (int i = 0; i< bool.length; i++) {
		         bool[i] = true;
		      }
		      for (int i = 2; i< Math.sqrt(num); i++) {
		         if(bool[i] == true) {
		            for(int j = (i*i); j<num; j = j+i) {
		               bool[j] = false;
		            }
		         }
		      }
		      if(num >= 0) {
		    	  bool[0] = false;
		    	  bool[1] = false;
		      }

		      return bool;
		}

	 static long modInverse(long a, long m)
	    {
	        long g = gcd(a, m);

	          return   power(a, m - 2, m);

	    }
	   static long lcm(long a , long b) {
		   return (a*b)/gcd(a, b);
	   }
	   static int lcm(int a , int b) {
		   return (int)((a*b)/gcd(a, b));
	   }
	 static long power(long x, long y, long m){
	        if (y == 0) return 1; long p = power(x, y / 2, m) % m; p = (int)((p * (long)p) % m);
	        if (y % 2 == 0) return p; else return (int)((x * (long)p) % m); }

     static class Combinations{
	    	 private long[] z;
	    	 private long[] z1;
	    	 private long[] z2;
	    	 private long mod;
	    	  public Combinations(long N , long mod) {
	    		  this.mod = mod;
				z = new long[(int)N+1];
				z1 = new long[(int)N+1];
				z[0] = 1;
				for(int i =1 ; i<=N ; i++) z[i] = (z[i-1]*i)%mod;
			     z2 = new long[(int)N+1];
				z2[0] = z2[1] = 1;
			    for (int i = 2; i <= N; i++)
			        z2[i] = z2[(int)(mod % i)] * (mod - mod / i) % mod;

			    z1[0] = z1[1] = 1;

			    for (int i = 2; i <= N; i++)
			        z1[i] = (z2[i] * z1[i - 1]) % mod;
			}
	    	  long fac(long n) {
	    		  return z[(int)n];
	    	  }
	    	  long invrsNum(long n) {
	    		  return z2[(int)n];
	    	  }
	    	  long invrsFac(long n) {
	    		  return invrsFac((int)n);
	    	  }
	    	  long ncr(long N, long R)
	    	  {		if(R<0 || R>N ) return 0;
	    		    long ans = ((z[(int)N] * z1[(int)R])
	    		              % mod * z1[(int)(N - R)])
	    		             % mod;
	    		    return ans;
	    		}
	      }
	      static class DisjointUnionSets {
			    int[] rank, parent;
			    int n;

			    public DisjointUnionSets(int n)
			    {
			        rank = new int[n];
			        parent = new int[n];
			        this.n = n;
			        makeSet();
			    }

			    void makeSet()
			    {
			        for (int i = 0; i < n; i++) {

			            parent[i] = i;
			        }
			    }

			    int find(int x)
			    {
			        if (parent[x] != x) {

			            parent[x] = find(parent[x]);

			        }

			        return parent[x];
			    }

			    void union(int x, int y)
			    {
			        int xRoot = find(x), yRoot = find(y);

			        if (xRoot == yRoot)
			            return;

			        if (rank[xRoot] < rank[yRoot])

			            parent[xRoot] = yRoot;

			        else if (rank[yRoot] < rank[xRoot])

			            parent[yRoot] = xRoot;

			        else
			        {
			            parent[yRoot] = xRoot;

			            rank[xRoot] = rank[xRoot] + 1;
			        }
			    }
			}
	      static int max(int... a ) {
	    	  int max = a[0];
	    	  for(int e:a) max = Math.max(max, e);
	    	  return max;
	      }
	      static long max(long... a ) {
	    	  long max = a[0];
	    	  for(long e:a) max = Math.max(max, e);
	    	  return max;
	      }
	      static int min(int... a ) {
	    	  int min = a[0];
	    	  for(int e:a) min = Math.min(e, min);
	    	  return min;
	      }
	      static long min(long... a ) {
	    	  long min = a[0];
	    	  for(long e:a) min = Math.min(e, min);
	    	  return min;
	      }
	      static int[] KMP(String str) {
	    	  int n = str.length();
	    	  int[] kmp = new int[n];
	    	  for(int i = 1 ; i<n ; i++) {
	    		  int j = kmp[i-1];
	    		  while(j>0 && str.charAt(i) != str.charAt(j)) {
	    			  j = kmp[j-1];
	    		  }
	    		  if(str.charAt(i) == str.charAt(j)) j++;
	    		  kmp[i] = j;
	    	  }

	    	  return kmp;
	      }

/************************************************ Query **************************************************************************************/

/***************************************** 		Sparse Table	********************************************************/
	      static class SparseTable{

	    		private long[][] st;

	    		SparseTable(long[] arr){
	    			int n = arr.length;
	    			st = new long[n][25];
	    			log = new int[n+2];
	    			build_log(n+1);
	    			build(arr);
	    		}

	    		private void build(long[] arr) {
	    			int n = arr.length;

	    			for(int i = n-1 ; i>=0 ; i--) {
	    				for(int j = 0 ; j<25 ; j++) {
	    					int r = i + (1<<j)-1;
	    					if(r>=n) break;
	    					if(j == 0 ) st[i][j] = arr[i];
	    					else st[i][j] = Math.min(st[i][j-1] , st[ i + ( 1 << (j-1) ) ][ j-1 ] );
	    				}
	    			}
	    		}
	    		public long gcd(long a  ,long b) {
	    			if(a == 0) return b;
	    			return gcd(b%a , a);
	    		}
	    		public long query(int l ,int r) {
	    			int w = r-l+1;
	    			int power = log[w];
	    			return Math.min(st[l][power],st[r - (1<<power) + 1][power]);
	    		}
	    		private int[] log;
	    		void build_log(int n) {
	    			log[1] = 0;
	    			for(int i = 2 ; i<=n ; i++) {
	    				log[i] = 1 + log[i/2];
	    			}
	    		}
	    	}

/********************************************************	Segement Tree	*****************************************************/
/**
	 	 static class SegmentTree{
			 long[] tree;
			 long[] arr;
			 int n;
			 SegmentTree(long[] arr){
				 this.n = arr.length;
				 tree = new long[4*n+1];
				 this.arr = arr;
				 buildTree(0, n-1, 1);
			 }

			  void buildTree(int s ,int e  ,int index ) {
					if(s == e) {
						tree[index] = arr[s];
						return;
					}

					int mid = (s+e)/2;

					buildTree( s,  mid, 2*index);
					buildTree( mid+1, e, 2*index+1);

					tree[index] = Math.min(tree[2*index] , tree[2*index+1]);
				}

			 long query(int si ,int ei) {
				 return query(0 ,n-1 , si ,ei , 1   );
			 }
			 private long query( int ss ,int se ,int qs , int qe,int index) {

					if(ss>=qs && se<=qe) return tree[index];

					if(qe<ss || se<qs) return (long)(1e17);

					int mid = (ss + se)/2;
					long left = query( ss , mid , qs ,qe , 2*index);
					long right= query(mid + 1 , se , qs ,qe , 2*index+1);
					return Math.min(left, right);
				}
			 public void update(int index , int val) {
				 arr[index] = val;
				 for(long e:arr) System.out.print(e+" ");
				 update(index , 0 , n-1 , 1);
			 }
			 private void update(int id ,int si , int ei , int index) {
				 if(id < si || id>ei) return;
				 if(si == ei ) {
					 tree[index] = arr[id];
					 return;
				 }
				 if(si > ei) return;
				 int mid = (ei + si)/2;

					update( id,  si, mid , 2*index);
					update( id , mid+1, ei , 2*index+1);

					tree[index] = Math.min(tree[2*index] ,tree[2*index+1]);
			 }

		 }
		 */

/* ***************************************************************************************************************************************************/

//	      static MyScanner sc = new MyScanner(); // only in case of less memory
	      static Reader sc = new Reader();
	 static StringBuilder sb = new StringBuilder();
	 public static void main(String args[]) throws IOException {

		 int tc = 1;
//		  tc = sc.nextInt();

		 for(int i = 1 ; i<=tc ; i++) {

//			 sb.append("Case #" + i + ": "  );	// During KickStart && HackerCup
			 TEST_CASE();

		 }
		 System.out.print(sb);
	 }
	 static void TEST_CASE() {
		char[] arr = sc.next().toCharArray();

		int n = arr.length;
		if(n == 1) {
			if(arr[0] == '0' || arr[0] == '_' || arr[0] == 'X' ) sb.append("1\n");
			else sb.append("0\n");
			return;
		}
		if(arr[0] == '0') {
			sb.append("0\n");
			return;
		}
		boolean bool = false;
		for(char cc:arr) {
			if(cc == 'X') {
				bool = true;
				break;
			}
		}
		long tot = 0;
		if(bool) {

			for(int i = 0 ; i<10;  i++) {
				char[] temp = new char[n];
				for(int j = 0 ; j<n ; j++)
					temp[j] = arr[j];
				if(temp[0] == 'X' && i == 0) continue;
				for(int j = 0 ; j<n ; j++) {
					if(temp[j] == 'X') {
						temp[j] = (char)(i + '0');
					}
				}

				// we have arr without X
				flag = false;
				long back = back(temp);
				long pre = 1;
				for(int j = 0 ; j<n-2 ; j++) {
					if(temp[j] == '_') {
						if(j == 0) pre *= 9;
						else pre *= 10;
					}
				}
				tot += pre*back;
				if(pre == 1 && flag) {
					tot--;
				}
			}
		}else {
			flag = false;
			long back = back(arr);
			long pre = 1;
			for(int j = 0 ;j<n-2 ; j++) {
				if(arr[j] == '_') {
					if(j == 0) pre *= 9;
					else pre *= 10;
				}
			}
			tot += pre*back;
			if(pre == 1 && flag) {
				tot--;
			}
		}

		sb.append(tot+"\n");

	 }
	 static boolean flag;
	 static long back(char[] arr ) {
//		 System.out.println(String.valueOf(arr));
		 long tot = 0;
		 int n = arr.length;
		 if(fnc(arr, n-1) && fnc(arr , n-2)) {
			 long num = Long.parseLong(""+arr[n-2] + arr[n-1]);
			 if(num%25 == 0) {
				 if(num == 0) flag = true;
				 return 1;
			 }
			 else return 0;
		 }else if(arr[n-1] == '_' && arr[n-2] == '_') {
			 flag = true;
			 return 4;
		 }else if(arr[n-1] == '_' ) {
			 if(arr[n-2] == '2' || arr[n-2] == '0' || arr[n-2] == '7' || arr[n-2] == '5')
			 {	if(arr[n-2] == '0') flag=  true;
				 return 1;
			 }

			 else return 0;
		 }else {
			 if(arr[n-1] == '0' || arr[n-1] == '5')
				 {
				 if(arr[n-1] == '0') flag = true;
				 return 2;
				 }
			 else return 0;
		 }
		 }
	 static boolean fnc(char[] arr , int i) {
		 return arr[i] != '_' ;
	 }
}
/*******************************************************************************************************************************************************/

/**

 */


import java.io.*;
import java.util.*;
// Problem Link: https://codeforces.com/problemset/problem/1575/D
public class div25 {
    public static char[] str;
    public static int S;
    public static void main (String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        str = in.readLine().toCharArray();
        S = str.length;
        int ans = 0;
        if (S==1) {
            if (str[0]=='X' || str[0] == '_' || Integer.parseInt(String.valueOf(str[0])) == 0) ans = 1;
        }
        else {
            ans += count_possibilities(2, 5);
            ans += count_possibilities(5, 0);
            ans += count_possibilities(7, 5);
            ans += count_possibilities(0, 0); }
        System.out.println(ans);

    }
    static int count_possibilities(int end1, int end2) {
        //System.out.println(end1 + " " + end2);
        if (S==2 && end1==0) return 0;
        int X_val = -1;
        if (str[S-2]=='X') X_val = end1;
        else {
            if (str[S-2]!='_') {
                if (value(S-2) != end1) return 0; } }
        //System.out.println("reached here");
        if (str[S-1]=='X') {
            if (X_val != -1 && end2 != X_val) return 0;
            else X_val = end2; }
        else {
            if (str[S-1]!='_') {
                if (value(S-1) != end2) return 0; } }
        //System.out.println("reached HERE");
        int total = 1;
        for (int i=0;i<S-2;i++) {
//            System.out.println(total);
//            System.out.println(X_val);
//            System.out.println(i + " " + str[i]);
            if (i==0) {
                if (str[i]=='X' && X_val==0) return 0;
                if (value(0) == 0) return 0; }
            if (str[i]=='_') {
                if (i==0) total *= 9;
                else total *= 10; }
            if (str[i]=='X') {
                if (X_val != -1) continue;
                else {
                    X_val = 10; // represents that X can be any integer from 0 to 9 (or possibly 1 to 9)
                    if (i==0) total *= 9;
                    else total *= 10;
                }
            }
        }
        //System.out.println(total);
        return total;
    }

    static boolean isDigit(int pos) {
        if (str[pos]=='_' || str[pos]=='X') return false;
        else return true;
    }

    static int value(int pos) {
        if (!isDigit(pos)) return -1;
        return Integer.parseInt(String.valueOf(str[pos]));
    }
}


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

public class Main {
    private static int solve(char[] s, char x) {
        for(int i = 0; i < s.length; i++) {
            if(s[i] == 'X') {
                s[i] = x;
            }
        }
        if(s[0] == '0') {
            return 0;
        }
        int ans = 1;
        boolean first = true;
        for(int i = 0; i < s.length; i++) {
            if(s[i] == '_') {
                ans *= i == 0 ? 9 : 10;
            } else if(s[i] == 'X' && first) {
                ans *= i == 0 ? 9 : 10;
                first = false;
            }
        }
        return ans;
    }
    private static boolean canReplace(char[] s, char a, char b) {
        if(s[s.length-2] >= '0' && s[s.length-2] <= '9' && s[s.length-2] != a) {
            return false;
        }
        if(s[s.length-1] >= '0' && s[s.length-1] <= '9' && s[s.length-1] != b) {
            return false;
        }
        if(s[s.length-2] == 'X' && s[s.length-1] == 'X' && a != b) {
            return false;
        }
        return true;
    }
    public static void main(String[] args) throws IOException{
        //BufferedReader f = new BufferedReader(new FileReader("cowjump.in"));
        BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
        //PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("cowjump.out")));
        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
        char[] s = f.readLine().toCharArray();
        if(s.length < 2) {
            out.println(s[0] == '0' || s[0] == '_' || s[0] == 'X' ? 1 : 0);
        } else {
            int ans = 0;
            if(canReplace(s, '0', '0')) {
                char[] t = s.clone();
                t[t.length-2] = '0';
                t[t.length-1] = '0';
                if(s[s.length-2] == 'X') {
                    ans += solve(t, t[t.length-2]);
                } else if(s[s.length-1] == 'X') {
                    ans += solve(t, t[t.length-1]);
                } else {
                    ans += solve(t, 'X');
                }
            }
            if(canReplace(s, '2', '5')) {
                char[] t = s.clone();
                t[t.length-2] = '2';
                t[t.length-1] = '5';
                if(s[s.length-2] == 'X') {
                    ans += solve(t, t[t.length-2]);
                } else if(s[s.length-1] == 'X') {
                    ans += solve(t, t[t.length-1]);
                } else {
                    ans += solve(t, 'X');
                }
            }
            if(canReplace(s, '5', '0')) {
                char[] t = s.clone();
                t[t.length-2] = '5';
                t[t.length-1] = '0';
                if(s[s.length-2] == 'X') {
                    ans += solve(t, t[t.length-2]);
                } else if(s[s.length-1] == 'X') {
                    ans += solve(t, t[t.length-1]);
                } else {
                    ans += solve(t, 'X');
                }
            }
            if(canReplace(s, '7', '5')) {
                char[] t = s.clone();
                t[t.length-2] = '7';
                t[t.length-1] = '5';
                if(s[s.length-2] == 'X') {
                    ans += solve(t, t[t.length-2]);
                } else if(s[s.length-1] == 'X') {
                    ans += solve(t, t[t.length-1]);
                } else {
                    ans += solve(t, 'X');
                }
            }
            out.println(ans);
        }
        f.close();
        out.close();
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Random;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.TreeMap;

// CFPS -> CodeForcesProblemSet
public final class CFPS {
	static FastReader fr = new FastReader();
	static PrintWriter out = new PrintWriter(System.out);
	static final int gigamod = 1000000007;
	static int t = 1;
	static double epsilon = 0.00000001;
	static boolean[] isPrime;
	static int[] smallestFactorOf;

	@SuppressWarnings("unused")
	public static void main(String[] args) {
		OUTER:
		for (int tc = 0; tc < t; tc++) {

			char[] sOG = fr.next().toCharArray();
			int n = sOG.length;

			if (n == 1) {
				if (sOG[0] == '0' || sOG[0] == '_' || sOG[0] == 'X')
					out.println(1);
				else
					out.println(0);
				continue OUTER;
			}

			// 00, 25, 50, 75 are the 4 universes
			// we'll count for all of them independently

			int answer = 0;

			{
				// 00
				// non _ and nonzero == death is true
				char[] s = sOG.clone();

				boolean shit = (s[n - 1] != '_' && s[n - 1] != 'X' && s[n - 1] != '0');
				shit |= (s[n - 2] != '_' && s[n - 2] != 'X' && s[n - 2] != '0');

				if (!shit) {

					if (s[n - 1] == 'X' || s[n - 2] == 'X')
						for (int i = 0; i < n; i++)
							if (s[i] == 'X')
								s[i] = '0';
					s[n - 1] = '0';
					s[n - 2] = '0';

					// now, we will iterate over all prefixes and
					// for each prefix, check whether it is possible to transform
					// s[] into (prefix + "00")

					// prefix has to be atmost 6 digits

					answer += check("00".toCharArray(), s);

					for (int num = 0; num < 1e6; num++) {
						char[] tgt = (Integer.toString(num) + "00").toCharArray();
						answer += check(tgt, s);
					}

				}
			}

			{
				// 25
				char[] s = sOG.clone();

				boolean shit = (s[n - 1] != '_' && s[n - 1] != 'X' && s[n - 1] != '5');
				shit |= s[n - 2] != '_' && s[n - 2] != 'X' && s[n - 2] != '2';
				shit |= (s[n - 1] == 'X' && s[n - 2] == 'X');

				if (!shit) {

					if (s[n - 1] == 'X') {

						// replace each by 5
						for (int i = 0; i < n; i++)
							if (s[i] == 'X')
								s[i] = '5';

					} else if (s[n - 2] == 'X') {

						// replace each by 2
						for (int i = 0; i < n; i++)
							if (s[i] == 'X')
								s[i] = '2';
					}

					s[n - 1] = '5';
					s[n - 2] = '2';

					answer += check("25".toCharArray(), s);

					for (int num = 0; num < 1e6; num++) {
						char[] tgt = (Integer.toString(num) + "25").toCharArray();
						answer += check(tgt, s);
					}
				}
			}

			{
				// 50
				char[] s = sOG.clone();

				boolean shit = (s[n - 1] != '_' && s[n - 1] != 'X' && s[n - 1] != '0');
				shit |= s[n - 2] != '_' && s[n - 2] != 'X' && s[n - 2] != '5';
				shit |= (s[n - 1] == 'X' && s[n - 2] == 'X');

				if (!shit) {

					if (s[n - 1] == 'X') {

						// replace each by 0
						for (int i = 0; i < n; i++)
							if (s[i] == 'X')
								s[i] = '0';

					} else if (s[n - 2] == 'X') {

						// replace each by 5
						for (int i = 0; i < n; i++)
							if (s[i] == 'X')
								s[i] = '5';
					}

					s[n - 1] = '0';
					s[n - 2] = '5';

					answer += check("50".toCharArray(), s);

					for (int num = 0; num < 1e6; num++) {
						char[] tgt = (Integer.toString(num) + "50").toCharArray();
						answer += check(tgt, s);
					}
				}
			}

			{
				// 75
				char[] s = sOG.clone();

				boolean shit = (s[n - 1] != '_' && s[n - 1] != 'X' && s[n - 1] != '5');
				shit |= s[n - 2] != '_' && s[n - 2] != 'X' && s[n - 2] != '7';
				shit |= (s[n - 1] == 'X' && s[n - 2] == 'X');

				if (!shit) {

					if (s[n - 1] == 'X') {

						// replace each by 5
						for (int i = 0; i < n; i++)
							if (s[i] == 'X')
								s[i] = '5';

					} else if (s[n - 2] == 'X') {

						// replace each by 7
						for (int i = 0; i < n; i++)
							if (s[i] == 'X')
								s[i] = '7';
					}

					s[n - 1] = '5';
					s[n - 2] = '7';

					answer += check("75".toCharArray(), s);

					for (int num = 0; num < 1e6; num++) {
						char[] tgt = (Integer.toString(num) + "75").toCharArray();
						answer += check(tgt, s);
					}
				}
			}

			out.println(answer);

			// out.println(check("34593925".toCharArray(), sOG));
		}
		out.close();
	}

	static int check(char[] tgt, char[] src) {
		int n = tgt.length;
		if (src.length != n) return 0;

		// 'X' check
		char xDig = 0;
		for (int i = 0; i < n; i++)
			if (src[i] == 'X') {
				if (xDig == 0) {
					xDig = tgt[i];
				} else {
					if (tgt[i] != xDig) return 0;
				}
			}
		// assert all 'X's have same digit;

		// no leading zeroes plz
		if (tgt[0] == '0') return 0;

		// all non _s have to be equal
		for (int i = 0; i < n; i++)
			if (src[i] != '_' && src[i] != 'X' && tgt[i] != src[i]) return 0;

		return 1;
	}

	static class Edge implements Comparable<Edge> {
		int from, to;
		long weight;
		int id;
		// int hash;

		Edge(int fro, int t, long weigh, int i) {
			from = fro;
			to = t;
			weight = weigh;
			id = i;
			// hash = Objects.hash(from, to, weight);
		}

		/*public int hashCode() {
			return hash;
		}*/

		public int compareTo(Edge that) {
			return Long.compare(this.id, that.id);
		}
	}

	public static long[][] sparseTable(long[] a)
	{
		int n = a.length;
		int b = 32-Integer.numberOfLeadingZeros(n);
		long[][] ret = new long[b][];
		for(int i = 0, l = 1;i < b;i++, l*=2) {
			if(i == 0) {
				ret[i] = a;
			}else {
				ret[i] = new long[n-l+1];
				for(int j = 0;j < n-l+1;j++) {
					ret[i][j] = Math.min(ret[i-1][j], ret[i-1][j+l/2]);
				}
			}
		}
		return ret;
	}

	public static long sparseRMQ(long[][] table, int l, int r)
	{
		// [a,b)
		assert l <= r;
		if(l >= r)return Integer.MAX_VALUE;
		// 1:0, 2:1, 3:1, 4:2, 5:2, 6:2, 7:2, 8:3
		int t = 31-Integer.numberOfLeadingZeros(r-l);
		return Math.min(table[t][l], table[t][r-(1<<t)]);
	}

	static class Point implements Comparable<Point> {
		long x;
		long y;
		long z;
		long id;
		// private int hashCode;

		Point() {
			x = z = y = 0;
			// this.hashCode = Objects.hash(x, y, cost);
		}

		Point(Point p) {
			this.x = p.x;
			this.y = p.y;
			this.z = p.z;
			this.id = p.id;
			// this.hashCode = Objects.hash(x, y, cost);
		}

		Point(long x, long y, long z, long id) {
			this.x = x;
			this.y = y;
			this.z = z;
			this.id = id;
			// this.hashCode = Objects.hash(x, y, id);
		}

		Point(long a, long b) {
			this.x = a;
			this.y = b;
			this.z = 0;
			// this.hashCode = Objects.hash(a, b);
		}

		Point(long x, long y, long id) {
			this.x = x;
			this.y = y;
			this.id = id;
		}

		@Override
		public int compareTo(Point o) {
			if (this.x < o.x)
				return -1;
			if (this.x > o.x)
				return 1;
			if (this.y < o.y)
				return -1;
			if (this.y > o.y)
				return 1;
			if (this.z < o.z)
				return -1;
			if (this.z > o.z)
				return 1;
			return 0;
		}

		@Override
		public boolean equals(Object that) {
			return this.compareTo((Point) that) == 0;
		}

		/*@Override
		public int hashCode() {
			return this.hashCode;
		}*/
	}

	static class BinaryLift {

		// FUNCTIONS: k-th ancestor and LCA in log(n)

		int[] parentOf;
		int maxJmpPow;
		int[][] binAncestorOf;
		int n;
		int[] lvlOf;

		// How this works?

		// a. For every node, we store the b-ancestor for b in {1, 2, 4, 8, .. log(n)}.

		// b. When we need k-ancestor, we represent 'k' in binary and for each set bit, we
		//    lift level in the tree.

		public BinaryLift(UGraph tree) {
			n = tree.V();
			maxJmpPow = logk(n, 2) + 1;
			parentOf = new int[n];
			binAncestorOf = new int[n][maxJmpPow];
			lvlOf = new int[n];
			for (int i = 0; i < n; i++)
				Arrays.fill(binAncestorOf[i], -1);
			parentConstruct(0, -1, tree, 0);
			binConstruct();
		}

		// TODO: Implement lvlOf[] initialization
		public BinaryLift(int[] parentOf) {
			this.parentOf = parentOf;
			n = parentOf.length;
			maxJmpPow = logk(n, 2) + 1;
			binAncestorOf = new int[n][maxJmpPow];
			lvlOf = new int[n];
			for (int i = 0; i < n; i++)
				Arrays.fill(binAncestorOf[i], -1);
			UGraph tree = new UGraph(n);
			for (int i = 1; i < n; i++)
				tree.addEdge(i, parentOf[i]);
			binConstruct();
			parentConstruct(0, -1, tree, 0);
		}

		private void parentConstruct(int current, int from, UGraph tree, int depth) {
			parentOf[current] = from;
			lvlOf[current] = depth;
			for (int adj : tree.adj(current))
				if (adj != from)
					parentConstruct(adj, current, tree, depth + 1);
		}

		private void binConstruct() {
			for (int node = 0; node < n; node++)
				for (int lvl = 0; lvl < maxJmpPow; lvl++)
					binConstruct(node, lvl);
		}

		private int binConstruct(int node, int lvl) {
			if (node < 0)
				return -1;
			if (lvl == 0)
				return binAncestorOf[node][lvl] = parentOf[node];
			if (node == 0)
				return binAncestorOf[node][lvl] = -1;

			if (binAncestorOf[node][lvl] != -1)
				return binAncestorOf[node][lvl];
			return binAncestorOf[node][lvl] = binConstruct(binConstruct(node, lvl - 1), lvl - 1);
		}

		// return ancestor which is 'k' levels above this one
		public int ancestor(int node, int k) {
			if (node < 0)
				return -1;
			if (node == 0)
				if (k == 0) return node;
				else return -1;
			if (k > (1 << maxJmpPow) - 1)
				return -1;
			if (k == 0)
				return node;

			int ancestor = node;
			int highestBit = Integer.highestOneBit(k);

			while (k > 0 && ancestor != -1) {
				ancestor = binAncestorOf[ancestor][logk(highestBit, 2)];
				k -= highestBit;
				highestBit = Integer.highestOneBit(k);
			}

			return ancestor;
		}

		public int lca(int u, int v) {

			if (u == v)
				return u;

			// The invariant will be that 'u' is below 'v' initially.
			if (lvlOf[u] < lvlOf[v]) {
				int temp = u;
				u = v;
				v = temp;
			}

			// Equalizing the levels.
			u = ancestor(u, lvlOf[u] - lvlOf[v]);

			if (u == v)
				return u;

			// We will now raise level by largest fitting power of two until possible.
			for (int power = maxJmpPow - 1; power > -1; power--)
				if (binAncestorOf[u][power] != binAncestorOf[v][power]) {
					u = binAncestorOf[u][power];
					v = binAncestorOf[v][power];
				}

			return ancestor(u, 1);
		}
	}

	static class DFSTree {

		// NOTE: The thing is made keeping in mind that the whole
		//  	 input graph is connected.

		UGraph tree;
		UGraph backUG;
		int hasBridge;
		int n;

		DFSTree(UGraph ug) {
			this.n = ug.V();
			tree = new UGraph(n);
			hasBridge = -1;
			backUG = new UGraph(n);
			treeCalc(0, -1, new boolean[n], ug);
		}

		private void treeCalc(int current, int from, boolean[] marked, UGraph ug) {
			if (marked[current]) {
				// This is a backEdge.
				backUG.addEdge(from, current);
				return;
			}

			if (from != -1)
				tree.addEdge(from, current);
			marked[current] = true;

			for (int adj : ug.adj(current))
				if (adj != from)
					treeCalc(adj, current, marked, ug);
		}

		public boolean hasBridge() {
			if (hasBridge != -1)
				return (hasBridge == 1);

			// We have to determine the bridge.
			bridgeFinder();
			return (hasBridge == 1);
		}

		int[] levelOf;
		int[] dp;

		private void bridgeFinder() {

			// Finding the level of each node.
			levelOf = new int[n];

			// Applying DP solution.
			// dp[i] -> Highest level reachable from subtree of 'i' using
			//   		some backEdge.
			dp = new int[n];
			Arrays.fill(dp, Integer.MAX_VALUE / 100);
			dpDFS(0, -1, 0);

			// Now, we will check each edge and determine whether its a
			// bridge.

			for (int i = 0; i < n; i++)
				for (int adj : tree.adj(i)) {

					// (i -> adj) is the edge.

					if (dp[adj] > levelOf[i])
						hasBridge = 1;
				}

			if (hasBridge != 1)
				hasBridge = 0;
		}

		private int dpDFS(int current, int from, int lvl) {
			levelOf[current] = lvl;
			dp[current] = levelOf[current];
			for (int back : backUG.adj(current))
				dp[current] = Math.min(dp[current], levelOf[back]);

			for (int adj : tree.adj(current))
				if (adj != from)
					dp[current] = Math.min(dp[current], dpDFS(adj, current, lvl + 1));

			return dp[current];
		}
	}

	static class UnionFind {
		// Uses weighted quick-union with path compression.
	    private int[] parent;  // parent[i] = parent of i
	    private int[] size;    // size[i] = number of sites in tree rooted at i
	                           // Note: not necessarily correct if i is not a root node
	    private int count;     // number of components

	    public UnionFind(int n) {
	        count = n;
	        parent = new int[n];
	        size = new int[n];
	        for (int i = 0; i < n; i++) {
	            parent[i] = i;
	            size[i] = 1;
	        }
	    }

	    // Number of connected components.
	    public int count() {
	        return count;
	    }

	    // Find the root of p.
	    public int find(int p) {
	    	while (p != parent[p])
	            p = parent[p];
	        return p;
	    }

	    public boolean connected(int p, int q) {
	        return find(p) == find(q);
	    }

	    public int numConnectedTo(int node) {
	    	return size[find(node)];
	    }

	    // Weighted union.
	    public void union(int p, int q) {
	        int rootP = find(p);
	        int rootQ = find(q);

	        if (rootP == rootQ) return;

	        // make smaller root point to larger one
	        if (size[rootP] < size[rootQ]) {
	            parent[rootP] = rootQ;
	            size[rootQ] += size[rootP];
	        }
	        else {
	            parent[rootQ] = rootP;
	            size[rootP] += size[rootQ];
	        }
	        count--;
	    }

	    public static int[] connectedComponents(UnionFind uf) {
	    	// We can do this in nlogn.

	    	int n = uf.size.length;
	    	int[] compoColors = new int[n];
	    	for (int i = 0; i < n; i++)
	    		compoColors[i] = uf.find(i);

	    	HashMap<Integer, Integer> oldToNew = new HashMap<>();
	    	int newCtr = 0;

	    	for (int i = 0; i < n; i++) {

	    		int thisOldColor = compoColors[i];
	    		Integer thisNewColor = oldToNew.get(thisOldColor);
	    		if (thisNewColor == null)
	    			thisNewColor = newCtr++;

	    		oldToNew.put(thisOldColor, thisNewColor);
	    		compoColors[i] = thisNewColor;
	    	}

	    	return compoColors;
	    }
	}

	static class UGraph {
		// Adjacency list.
		private HashSet<Integer>[] adj;
		private static final String NEWLINE = "\n";
		private int E;

		@SuppressWarnings("unchecked")
		public UGraph(int V) {
			adj = (HashSet<Integer>[]) new HashSet[V];
			E = 0;
			for (int i = 0; i < V; i++)
				adj[i] = new HashSet<Integer>();
		}

		public void addEdge(int from, int to) {
			if (adj[from].contains(to)) return;
			E++;
			adj[from].add(to);
			adj[to].add(from);
		}

		public HashSet<Integer> adj(int from) {
			return adj[from];
		}

		public int degree(int v) {
			return adj[v].size();
		}

		public int V() {
			return adj.length;
		}

		public int E() {
			return E;
		}

		public String toString() {
			StringBuilder s = new StringBuilder();
			s.append(V() + " vertices, " + E() + " edges " + NEWLINE);
			for (int v = 0; v < V(); v++) {
				s.append(v + ": ");
				for (int w : adj[v]) {
					s.append(w + " ");
				}
				s.append(NEWLINE);
			}
			return s.toString();
		}

		public static void dfsMark(int current, boolean[] marked, UGraph g) {
			if (marked[current]) return;

			marked[current] = true;
			Iterable<Integer> adj = g.adj(current);
			for (int adjc : adj)
				dfsMark(adjc, marked, g);
		}

		public static void dfsMark(int current, int from, long[] distTo, boolean[] marked, UGraph g, ArrayList<Integer> endPoints) {
			if (marked[current]) return;

			marked[current] = true;
			if (from != -1)
				distTo[current] = distTo[from] + 1;
			HashSet<Integer> adj = g.adj(current);
			int alreadyMarkedCtr = 0;
			for (int adjc : adj) {
				if (marked[adjc]) alreadyMarkedCtr++;
				dfsMark(adjc, current, distTo, marked, g, endPoints);
			}

			if (alreadyMarkedCtr == adj.size())
				endPoints.add(current);
		}

		public static void bfsOrder(int current, UGraph g) {
		}

		public static void dfsMark(int current, int[] colorIds, int color, UGraph g) {
			if (colorIds[current] != -1) return;

			colorIds[current] = color;
			Iterable<Integer> adj = g.adj(current);
			for (int adjc : adj)
				dfsMark(adjc, colorIds, color, g);
		}

		public static int[] connectedComponents(UGraph g) {
			int n = g.V();
			int[] componentId = new int[n];
			Arrays.fill(componentId, -1);
			int colorCtr = 0;
			for (int i = 0; i < n; i++) {
				if (componentId[i] != -1) continue;
				dfsMark(i, componentId, colorCtr, g);
				colorCtr++;
			}

			return componentId;
		}

		public static boolean hasCycle(UGraph ug) {
			int n = ug.V();
			boolean[] marked = new boolean[n];
			boolean[] hasCycleFirst = new boolean[1];
			for (int i = 0; i < n; i++) {
				if (marked[i]) continue;
				hcDfsMark(i, ug, marked, hasCycleFirst, -1);
			}
			return hasCycleFirst[0];
		}

		// Helper for hasCycle.
		private static void hcDfsMark(int current, UGraph ug, boolean[] marked, boolean[] hasCycleFirst, int parent) {
			if (marked[current]) return;
			if (hasCycleFirst[0]) return;

			marked[current] = true;
			HashSet<Integer> adjc = ug.adj(current);
			for (int adj : adjc) {
				if (marked[adj] && adj != parent && parent != -1) {
					hasCycleFirst[0] = true;
					return;
				}

				hcDfsMark(adj, ug, marked, hasCycleFirst, current);
			}
		}
	}

	static class Digraph {
		// Adjacency list.
		private HashSet<Integer>[] adj;
		private static final String NEWLINE = "\n";
		private int E;

		@SuppressWarnings("unchecked")
		public Digraph(int V) {
			adj = (HashSet<Integer>[]) new HashSet[V];
			E = 0;
			for (int i = 0; i < V; i++)
				adj[i] = new HashSet<Integer>();
		}

		public void addEdge(int from, int to) {
			if (adj[from].contains(to)) return;
			E++;
			adj[from].add(to);
		}

		public HashSet<Integer> adj(int from) {
			return adj[from];
		}

		public int V() {
			return adj.length;
		}

		public int E() {
			return E;
		}

		public Digraph reversed() {
			Digraph dg = new Digraph(V());
			for (int i = 0; i < V(); i++)
				for (int adjVert : adj(i)) dg.addEdge(adjVert, i);
			return dg;
		}

		public String toString() {
			StringBuilder s = new StringBuilder();
			s.append(V() + " vertices, " + E() + " edges " + NEWLINE);
			for (int v = 0; v < V(); v++) {
				s.append(v + ": ");
				for (int w : adj[v]) {
					s.append(w + " ");
				}
				s.append(NEWLINE);
			}
			return s.toString();
		}

		public static int[] KosarajuSharirSCC(Digraph dg) {
			int[] id = new int[dg.V()];

			Digraph reversed = dg.reversed();

			// Gotta perform topological sort on this one to get the stack.
			Stack<Integer> revStack = Digraph.topologicalSort(reversed);

			// Initializing id and idCtr.
			id = new int[dg.V()];
			int idCtr = -1;

			// Creating a 'marked' array.
			boolean[] marked = new boolean[dg.V()];

			while (!revStack.isEmpty()) {
				int vertex = revStack.pop();
				if (!marked[vertex])
					sccDFS(dg, vertex, marked, ++idCtr, id);
			}
			return id;
		}

		private static void sccDFS(Digraph dg, int source, boolean[] marked, int idCtr, int[] id) {
			marked[source] = true;
			id[source] = idCtr;
			for (Integer adjVertex : dg.adj(source))
				if (!marked[adjVertex]) sccDFS(dg, adjVertex, marked, idCtr, id);
		}

		public static Stack<Integer> topologicalSort(Digraph dg) {
			// dg has to be a directed acyclic graph.
			// We'll have to run dfs on the digraph and push the deepest nodes on stack first.
			// We'll need a Stack<Integer> and a int[] marked.
			Stack<Integer> topologicalStack = new Stack<Integer>();
			boolean[] marked = new boolean[dg.V()];

			// Calling dfs
			for (int i = 0; i < dg.V(); i++)
				if (!marked[i])
					runDfs(dg, topologicalStack, marked, i);

			return topologicalStack;
		}

		static void runDfs(Digraph dg, Stack<Integer> topologicalStack, boolean[] marked, int source) {
			marked[source] = true;
			for (Integer adjVertex : dg.adj(source))
				if (!marked[adjVertex])
					runDfs(dg, topologicalStack, marked, adjVertex);
			topologicalStack.add(source);
		}
	}

	static class FastReader {
		private BufferedReader bfr;
		private StringTokenizer st;
		public FastReader() {
			bfr = new BufferedReader(new InputStreamReader(System.in));
		}

		String next() {
			if (st == null || !st.hasMoreElements()) {
				try {
					st = new StringTokenizer(bfr.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());
		}

		char nextChar() {
			return next().toCharArray()[0];
		}

		String nextString() {
			return next();
		}

		int[] nextIntArray(int n) {
			int[] arr = new int[n];
			for (int i = 0; i < n; i++)
				arr[i] = nextInt();
			return arr;
		}

		double[] nextDoubleArray(int n) {
			double[] arr = new double[n];
			for (int i = 0; i < arr.length; i++)
				arr[i] = nextDouble();
			return arr;
		}

		long[] nextLongArray(int n) {
			long[] arr = new long[n];
			for (int i = 0; i < n; i++)
				arr[i] = nextLong();
			return arr;
		}

		int[][] nextIntGrid(int n, int m) {
			int[][] grid = new int[n][m];
			for (int i = 0; i < n; i++) {
				for (int j = 0; j < m; j++)
					grid[i][j] = fr.nextInt();
			}
			return grid;
		}
	}

	static class LCA {
	    int[] height, first, segtree;
	    ArrayList<Integer> euler;
	    boolean[] visited;
	    int n;

	    LCA(UGraph ug, int root) {
	        n = ug.V();
	        height = new int[n];
	        first = new int[n];
	        euler = new ArrayList<>();
	        visited = new boolean[n];
	        dfs(ug, root, 0);
	        int m = euler.size();
	        segtree = new int[m * 4];
	        build(1, 0, m - 1);
	    }

	    void dfs(UGraph ug, int node, int h) {
	        visited[node] = true;
	        height[node] = h;
	        first[node] = euler.size();
	        euler.add(node);
	        for (int adj : ug.adj(node)) {
	            if (!visited[adj]) {
	                dfs(ug, adj, h + 1);
	                euler.add(node);
	            }
	        }
	    }

	    void build(int node, int b, int e) {
	        if (b == e) {
	            segtree[node] = euler.get(b);
	        } else {
	            int mid = (b + e) / 2;
	            build(node << 1, b, mid);
	            build(node << 1 | 1, mid + 1, e);
	            int l = segtree[node << 1], r = segtree[node << 1 | 1];
	            segtree[node] = (height[l] < height[r]) ? l : r;
	        }
	    }

	    int query(int node, int b, int e, int L, int R) {
	        if (b > R || e < L)
	            return -1;
	        if (b >= L && e <= R)
	            return segtree[node];
	        int mid = (b + e) >> 1;

	        int left = query(node << 1, b, mid, L, R);
	        int right = query(node << 1 | 1, mid + 1, e, L, R);
	        if (left == -1) return right;
	        if (right == -1) return left;
	        return height[left] < height[right] ? left : right;
	    }

	    int lca(int u, int v) {
	        int left = first[u], right = first[v];
	        if (left > right) {
	        	int temp = left;
	        	left = right;
	        	right = temp;
	        }
	        return query(1, 0, euler.size() - 1, left, right);
	    }
	}

	static class FenwickTree {

	    long[] array; // 1-indexed array, In this array We save cumulative information to perform efficient range queries and updates

	    public FenwickTree(int size) {
	        array = new long[size + 1];
	    }

	    public long rsq(int ind) {
	        assert ind > 0;
	        long sum = 0;
	        while (ind > 0) {
	            sum += array[ind];
	            //Extracting the portion up to the first significant one of the binary representation of 'ind' and decrementing ind by that number
	            ind -= ind & (-ind);
	        }

	        return sum;
	    }

	    public long rsq(int a, int b) {
	        assert b >= a && a > 0 && b > 0;

	        return rsq(b) - rsq(a - 1);
	    }

	    public void update(int ind, long value) {
	        assert ind > 0;
	        while (ind < array.length) {
	            array[ind] += value;
	            //Extracting the portion up to the first significant one of the binary representation of 'ind' and incrementing ind by that number
	            ind += ind & (-ind);
	        }
	    }

	    public int size() {
	        return array.length - 1;
	    }
	}

	static class SegmentTree {

	    private Node[] heap;
	    private long[] array;
	    private int size;

	    public SegmentTree(long[] array) {
	        this.array = Arrays.copyOf(array, array.length);
	        //The max size of this array is about 2 * 2 ^ log2(n) + 1
	        size = (int) (2 * Math.pow(2.0, Math.floor((Math.log((double) array.length) / Math.log(2.0)) + 1)));
	        heap = new Node[size];
	        build(1, 0, array.length);
	    }

	    public int size() {
	        return array.length;
	    }

	    //Initialize the Nodes of the Segment tree
	    private void build(int v, int from, int size) {
	        heap[v] = new Node();
	        heap[v].from = from;
	        heap[v].to = from + size - 1;

	        if (size == 1) {
	            heap[v].sum = array[from];
	            heap[v].min = array[from];
	            heap[v].max = array[from];
	        } else {
	            //Build childs
	            build(2 * v, from, size / 2);
	            build(2 * v + 1, from + size / 2, size - size / 2);

	            heap[v].sum = heap[2 * v].sum + heap[2 * v + 1].sum;
	            //min = min of the children
	            heap[v].min = Math.min(heap[2 * v].min, heap[2 * v + 1].min);
	            heap[v].max = Math.max(heap[2 * v].max, heap[2 * v + 1].max);
	        }
	    }

	    public long rsq(int from, int to) {
	        return rsq(1, from, to);
	    }

	    private long rsq(int v, int from, int to) {
	        Node n = heap[v];

	        //If you did a range update that contained this node, you can infer the Sum without going down the tree
	        if (n.pendingVal != null && contains(n.from, n.to, from, to)) {
	            return (to - from + 1) * n.pendingVal;
	        }

	        if (contains(from, to, n.from, n.to)) {
	            return heap[v].sum;
	        }

	        if (intersects(from, to, n.from, n.to)) {
	            propagate(v);
	            long leftSum = rsq(2 * v, from, to);
	            long rightSum = rsq(2 * v + 1, from, to);

	            return leftSum + rightSum;
	        }

	        return 0;
	    }

	    public long rMinQ(int from, int to) {
	        return rMinQ(1, from, to);
	    }

	    private long rMinQ(int v, int from, int to) {
	        Node n = heap[v];

	        //If you did a range update that contained this node, you can infer the Min value without going down the tree
	        if (n.pendingVal != null && contains(n.from, n.to, from, to)) {
	            return n.pendingVal;
	        }

	        if (contains(from, to, n.from, n.to)) {
	            return heap[v].min;
	        }

	        if (intersects(from, to, n.from, n.to)) {
	            propagate(v);
	            long leftMin = rMinQ(2 * v, from, to);
	            long rightMin = rMinQ(2 * v + 1, from, to);

	            return Math.min(leftMin, rightMin);
	        }

	        return Integer.MAX_VALUE;
	    }

	    public long rMaxQ(int from, int to) {
	        return rMaxQ(1, from, to);
	    }

	    private long rMaxQ(int v, int from, int to) {
	        Node n = heap[v];

	        //If you did a range update that contained this node, you can infer the Min value without going down the tree
	        if (n.pendingVal != null && contains(n.from, n.to, from, to)) {
	            return n.pendingVal;
	        }

	        if (contains(from, to, n.from, n.to)) {
	            return heap[v].max;
	        }

	        if (intersects(from, to, n.from, n.to)) {
	            propagate(v);
	            long leftMax = rMaxQ(2 * v, from, to);
	            long rightMax = rMaxQ(2 * v + 1, from, to);

	            return Math.max(leftMax, rightMax);
	        }

	        return Integer.MIN_VALUE;
	    }

	    public void update(int from, int to, long value) {
	        update(1, from, to, value);
	    }

	    private void update(int v, int from, int to, long value) {

	        //The Node of the heap tree represents a range of the array with bounds: [n.from, n.to]
	        Node n = heap[v];

	        if (contains(from, to, n.from, n.to)) {
	            change(n, value);
	        }

	        if (n.size() == 1) return;

	        if (intersects(from, to, n.from, n.to)) {
	            propagate(v);

	            update(2 * v, from, to, value);
	            update(2 * v + 1, from, to, value);

	            n.sum = heap[2 * v].sum + heap[2 * v + 1].sum;
	            n.min = Math.min(heap[2 * v].min, heap[2 * v + 1].min);
	            n.max = Math.max(heap[2 * v].max, heap[2 * v + 1].max);
	        }
	    }

	    //Propagate temporal values to children
	    private void propagate(int v) {
	        Node n = heap[v];

	        if (n.pendingVal != null) {
	            change(heap[2 * v], n.pendingVal);
	            change(heap[2 * v + 1], n.pendingVal);
	            n.pendingVal = null; //unset the pending propagation value
	        }
	    }

	    //Save the temporal values that will be propagated lazily
	    private void change(Node n, long value) {
	        n.pendingVal = value;
	        n.sum = n.size() * value;
	        n.min = value;
	        n.max = value;
	        array[n.from] = value;
	    }

	    //Test if the range1 contains range2
	    private boolean contains(int from1, int to1, int from2, int to2) {
	        return from2 >= from1 && to2 <= to1;
	    }

	    //check inclusive intersection, test if range1[from1, to1] intersects range2[from2, to2]
	    private boolean intersects(int from1, int to1, int from2, int to2) {
	        return from1 <= from2 && to1 >= from2   //  (.[..)..] or (.[...]..)
	                || from1 >= from2 && from1 <= to2; // [.(..]..) or [..(..)..
	    }

	    //The Node class represents a partition range of the array.
	    static class Node {
	        long sum;
	        long min;
	        long max;
	        //Here we store the value that will be propagated lazily
	        Long pendingVal = null;
	        int from;
	        int to;

	        int size() {
	            return to - from + 1;
	        }
	    }
	}

	@SuppressWarnings("serial")
	static class CountMap<T> extends TreeMap<T, Integer>{

		CountMap() {
		}

		CountMap(T[] arr) {
			this.putCM(arr);
		}

		public Integer putCM(T key) {
			return super.put(key, super.getOrDefault(key, 0) + 1);
		}

		public Integer removeCM(T key) {
			int count = super.getOrDefault(key, -1);
			if (count == -1) return -1;
			if (count == 1)
				return super.remove(key);
			else
				return super.put(key, count - 1);
		}

		public Integer getCM(T key) {
			return super.getOrDefault(key, 0);
		}

		public void putCM(T[] arr) {
			for (T l : arr)
				this.putCM(l);
		}
	}

	static long dioGCD(long a, long b, long[] x0, long[] y0) {
	    if (b == 0) {
	        x0[0] = 1;
	        y0[0] = 0;
	        return a;
	    }
	    long[] x1 = new long[1], y1 = new long[1];
	    long d = dioGCD(b, a % b, x1, y1);
	    x0[0] = y1[0];
	    y0[0] = x1[0] - y1[0] * (a / b);
	    return d;
	}

	static boolean diophantine(long a, long b, long c, long[] x0, long[] y0, long[] g) {
	    g[0] = dioGCD(Math.abs(a), Math.abs(b), x0, y0);
	    if (c % g[0] > 0) {
	        return false;
	    }

	    x0[0] *= c / g[0];
	    y0[0] *= c / g[0];
	    if (a < 0) x0[0] = -x0[0];
	    if (b < 0) y0[0] = -y0[0];
	    return true;
	}

	static long[][] prod(long[][] mat1, long[][] mat2) {
		int n = mat1.length;
		long[][] prod = new long[n][n];

		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
				// determining prod[i][j]
				// it will be the dot product of mat1[i][] and mat2[][i]
				for (int k = 0; k < n; k++)
					prod[i][j] += mat1[i][k] * mat2[k][j];
		return prod;
	}
	static long[][] matExpo(long[][] mat, long power) {
		int n = mat.length;
		long[][] ans = new long[n][n];

		if (power == 0)
			return null;

		if (power == 1)
			return mat;

		long[][] half = matExpo(mat, power / 2);
		ans = prod(half, half);

		if (power % 2 == 1) {
			ans = prod(ans, mat);
		}

		return ans;
	}

	static int KMPNumOcc(char[] text, char[] pat) {
		int n = text.length;
		int m = pat.length;

		char[] patPlusText = new char[n + m + 1];
		for (int i = 0; i < m; i++)
			patPlusText[i] = pat[i];
		patPlusText[m] = '^'; 		// Seperator
		for (int i = 0; i < n; i++)
			patPlusText[m + i] = text[i];

		int[] fullPi = piCalcKMP(patPlusText);
		int answer = 0;
		for (int i = 0; i < n + m + 1; i++)
			if (fullPi[i] == m)
				answer++;
		return answer;
	}
	static int[] piCalcKMP(char[] s) {
		int n = s.length;
		int[] pi = new int[n];
		for (int i = 1; i < n; i++) {
			int j = pi[i - 1];
			while (j > 0 && s[i] != s[j])
				j = pi[j - 1];
			if (s[i] == s[j])
				j++;
			pi[i] = j;
		}
		return pi;
	}
	static long hash(long key) {
        long h = Long.hashCode(key);
        h ^= (h >>> 20) ^ (h >>> 12) ^ (h >>> 7) ^ (h >>> 4);
        return h & (gigamod-1);
    }

	static int mapTo1D(int row, int col, int n, int m) {
		// Maps elements in a 2D matrix serially to elements in
		// a 1D array.
		return row * m + col;
	}
	static int[] mapTo2D(int idx, int n, int m) {
		// Inverse of what the one above does.
		int[] rnc = new int[2];
		rnc[0] = idx / m;
		rnc[1] = idx % m;
		return rnc;
	}

	static boolean[] primeGenerator(int upto) {
		// Sieve of Eratosthenes:
		isPrime = new boolean[upto + 1];
		smallestFactorOf = new int[upto + 1];
		Arrays.fill(smallestFactorOf, 1);
		Arrays.fill(isPrime, true);
		isPrime[1] = isPrime[0] = false;

		for (long i = 2; i < upto + 1; i++)
			if (isPrime[(int) i]) {
				smallestFactorOf[(int) i] = (int) i;
				// Mark all the multiples greater than or equal
				// to the square of i to be false.
				for (long j = i; j * i < upto + 1; j++) {
					if (isPrime[(int) j * (int) i]) {
						isPrime[(int) j * (int) i] = false;
						smallestFactorOf[(int) j * (int) i] = (int) i;
					}
				}
			}
		return isPrime;
	}
	static HashMap<Integer, Integer> smolNumPrimeFactorization(int num) {
		if (smallestFactorOf == null)
			primeGenerator(num + 1);
		HashMap<Integer, Integer> fnps = new HashMap<>();
		while (num != 1) {
			fnps.put(smallestFactorOf[num], fnps.getOrDefault(smallestFactorOf[num], 0) + 1);
			num /= smallestFactorOf[num];
		}
		return fnps;
	}
	static HashMap<Long, Integer> primeFactorization(long num) {
		// Returns map of factor and its power in the number.
		HashMap<Long, Integer> map = new HashMap<>();
		while (num % 2 == 0) {
			num /= 2;
			Integer pwrCnt = map.get(2L);
			map.put(2L, pwrCnt != null ? pwrCnt + 1 : 1);
		}
		for (long i = 3; i * i <= num; i += 2) {
			while (num % i == 0) {
				num /= i;
				Integer pwrCnt = map.get(i);
				map.put(i, pwrCnt != null ? pwrCnt + 1 : 1);
			}
		}
		// If the number is prime, we have to add it to the
		// map.
		if (num != 1)
			map.put(num, 1);
		return map;
	}
	static HashSet<Long> divisors(long num) {
		HashSet<Long> divisors = new HashSet<Long>();
		divisors.add(1L);
		divisors.add(num);
		for (long i = 2; i * i <= num; i++) {
			if (num % i == 0) {
				divisors.add(num/i);
				divisors.add(i);
			}
		}
		return divisors;
	}
	static void coprimeGenerator(int m, int n, ArrayList<Point> coprimes, int limit, int numCoprimes) {
		if (m > limit) return;
		if (m <= limit && n <= limit)
			coprimes.add(new Point(m, n));
		if (coprimes.size() > numCoprimes) return;
		coprimeGenerator(2 * m - n, m, coprimes, limit, numCoprimes);
		coprimeGenerator(2 * m + n, m, coprimes, limit, numCoprimes);
		coprimeGenerator(m + 2 * n, n, coprimes, limit, numCoprimes);
	}

	static int bsearch(int[] arr, int val, int lo, int hi) {
		// Returns the index of the first element
		// larger than or equal to val.
		int idx = -1;
		while (lo <= hi) {
			int mid = lo + (hi - lo)/2;
			if (arr[mid] >= val) {
				idx = mid;
				hi = mid - 1;
			} else
				lo = mid + 1;
		}
		return idx;
	}
	static int bsearch(long[] arr, long val, int lo, int hi) {
		// Returns the index of the first element
		// larger than or equal to val.
		int idx = -1;
		while (lo <= hi) {
			int mid = lo + (hi - lo)/2;
			if (arr[mid] >= val) {
				idx = mid;
				hi = mid - 1;
			} else
				lo = mid + 1;
		}
		return idx;
	}
	static int bsearch(long[] arr, long val, int lo, int hi, boolean sMode) {
		// Returns the index of the last element
		// smaller than or equal to val.
		int idx = -1;
		while (lo <= hi) {
			int mid = lo + (hi - lo)/2;
			if (arr[mid] > val) {
				hi = mid - 1;
			} else {
				idx = mid;
				lo = mid + 1;
			}
		}
		return idx;
	}
	static int bsearch(int[] arr, long val, int lo, int hi, boolean sMode) {
		int idx = -1;
		while (lo <= hi) {
			int mid = lo + (hi - lo)/2;
			if (arr[mid] > val) {
				hi = mid - 1;
			} else {
				idx = mid;
				lo = mid + 1;
			}
		}
		return idx;
	}

	static long nCr(long n, long r, long[] fac) { long p = gigamod; if (r == 0) return 1; return (fac[(int)n] * modInverse(fac[(int)r], p) % p * modInverse(fac[(int)n - (int)r], p) % p) % p; }
	static long modInverse(long n, long p) { return power(n, p - 2, p); }
	static long modDiv(long a, long b){return mod(a * power(b, gigamod - 2, gigamod));}
	static long power(long x, long y, long p) { long res = 1; x = x % p; while (y > 0) { if ((y & 1)==1) res = (res * x) % p; y = y >> 1; x = (x * x) % p; } return res; }
	static int logk(long n, long k) { return (int)(Math.log(n) / Math.log(k)); }
	static long gcd(long a, long b) { if (b == 0) { return a; } else { return gcd(b, a % b); } } static int gcd(int a, int b) { if (b == 0) { return a; } else { return gcd(b, a % b); } } static long gcd(long[] arr) { int n = arr.length; long gcd = arr[0]; for (int i = 1; i < n; i++) { gcd = gcd(gcd, arr[i]); } return gcd; } static int gcd(int[] arr) { int n = arr.length; int gcd = arr[0]; for (int i = 1; i < n; i++) { gcd = gcd(gcd, arr[i]); } return gcd; } static long lcm(long[] arr) { long lcm = arr[0]; int n = arr.length; for (int i = 1; i < n; i++) { lcm = (lcm * arr[i]) / gcd(lcm, arr[i]); } return lcm; } static long lcm(long a, long b) { return (a * b)/gcd(a, b); } static boolean less(int a, int b) { return a < b ? true : false; } static boolean isSorted(int[] a) { for (int i = 1; i < a.length; i++) { if (less(a[i], a[i - 1])) return false; } return true; } static boolean isSorted(long[] a) { for (int i = 1; i < a.length; i++) { if (a[i] < a[i - 1]) return false; } return true; } static void swap(int[] a, int i, int j) { int temp = a[i]; a[i] = a[j]; a[j] = temp; } static void swap(long[] a, int i, int j) { long temp = a[i]; a[i] = a[j]; a[j] = temp; } static void swap(double[] a, int i, int j) { double temp = a[i]; a[i] = a[j]; a[j] = temp; } static void swap(char[] a, int i, int j) { char temp = a[i]; a[i] = a[j]; a[j] = temp; }
	static void sort(int[] arr) { shuffleArray(arr, 0, arr.length - 1); Arrays.sort(arr); } static void sort(char[] arr) { shuffleArray(arr, 0, arr.length - 1); Arrays.sort(arr); } static void sort(long[] arr) { shuffleArray(arr, 0, arr.length - 1); Arrays.sort(arr); } static void sort(double[] arr) { shuffleArray(arr, 0, arr.length - 1); Arrays.sort(arr); } static void reverseSort(int[] arr) { shuffleArray(arr, 0, arr.length - 1); Arrays.sort(arr); int n = arr.length; for (int i = 0; i < n/2; i++) swap(arr, i, n - 1 - i); } static void reverseSort(char[] arr) { shuffleArray(arr, 0, arr.length - 1); Arrays.sort(arr); int n = arr.length; for (int i = 0; i < n/2; i++) swap(arr, i, n - 1 - i); } static void reverse(char[] arr) { int n = arr.length; for (int i = 0; i < n / 2; i++) swap(arr, i, n - 1 - i); } static void reverseSort(long[] arr) { shuffleArray(arr, 0, arr.length - 1); Arrays.sort(arr); int n = arr.length; for (int i = 0; i < n/2; i++) swap(arr, i, n - 1 - i); } static void reverseSort(double[] arr) { shuffleArray(arr, 0, arr.length - 1); Arrays.sort(arr); int n = arr.length; for (int i = 0; i < n/2; i++) swap(arr, i, n - 1 - i); }
	static void shuffleArray(long[] arr, int startPos, int endPos) { Random rnd = new Random(); for (int i = startPos; i < endPos; ++i) { long tmp = arr[i]; int randomPos = i + rnd.nextInt(endPos - i); arr[i] = arr[randomPos]; arr[randomPos] = tmp; } } static void shuffleArray(int[] arr, int startPos, int endPos) { Random rnd = new Random(); for (int i = startPos; i < endPos; ++i) { int tmp = arr[i]; int randomPos = i + rnd.nextInt(endPos - i); arr[i] = arr[randomPos]; arr[randomPos] = tmp; } }
	static void shuffleArray(double[] arr, int startPos, int endPos) { Random rnd = new Random(); for (int i = startPos; i < endPos; ++i) { double tmp = arr[i]; int randomPos = i + rnd.nextInt(endPos - i); arr[i] = arr[randomPos]; arr[randomPos] = tmp; } }
	static void shuffleArray(char[] arr, int startPos, int endPos) { Random rnd = new Random(); for (int i = startPos; i < endPos; ++i) { char tmp = arr[i]; int randomPos = i + rnd.nextInt(endPos - i); arr[i] = arr[randomPos]; arr[randomPos] = tmp; } }
	static boolean isPrime(long n) {if (n<=1)return false;if(n<=3)return true;if(n%2==0||n%3==0)return false;for(long i=5;i*i<=n;i=i+6)if(n%i==0||n%(i+2)==0)return false;return true;}
	static String toString(int[] dp){StringBuilder sb=new StringBuilder();for(int i=0;i<dp.length;i++)sb.append(dp[i]+" ");return sb.toString();}
	static String toString(boolean[] dp){StringBuilder sb=new StringBuilder();for(int i=0;i<dp.length;i++)sb.append(dp[i]+" ");return sb.toString();}
	static String toString(long[] dp){StringBuilder sb=new StringBuilder();for(int i=0;i<dp.length;i++)sb.append(dp[i]+" ");return sb.toString();}
	static String toString(char[] dp){StringBuilder sb=new StringBuilder();for(int i=0;i<dp.length;i++)sb.append(dp[i]+"");return sb.toString();}
	static String toString(int[][] dp){StringBuilder sb=new StringBuilder();for(int i=0;i<dp.length;i++){for(int j=0;j<dp[i].length;j++){sb.append(dp[i][j]+" ");}sb.append('\n');}return sb.toString();}
	static String toString(long[][] dp){StringBuilder sb=new StringBuilder();for(int i=0;i<dp.length;i++){for(int j=0;j<dp[i].length;j++) {sb.append(dp[i][j]+" ");}sb.append('\n');}return sb.toString();}
	static String toString(double[][] dp){StringBuilder sb=new StringBuilder();for(int i = 0;i<dp.length;i++){for(int j = 0;j<dp[i].length;j++){sb.append(dp[i][j]+" ");}sb.append('\n');}return sb.toString();}
	static String toString(char[][] dp){StringBuilder sb = new StringBuilder();for(int i = 0;i<dp.length;i++){for(int j = 0;j<dp[i].length;j++){sb.append(dp[i][j]+"");}sb.append('\n');}return sb.toString();}
	static long mod(long a, long m){return(a%m+1000000L*m)%m;}
	static long mod(long num){return(num%gigamod+gigamod)%gigamod;}
}

// NOTES:
// ASCII VALUE OF 'A': 65
// ASCII VALUE OF 'a': 97
// Range of long: 9 * 10^18
// ASCII VALUE OF '0': 48
// Primes upto 'n' can be given by (n / (logn)).


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

public class B{

    public static int takeInt(BufferedReader br)throws IOException{
        int n=Integer.parseInt(br.readLine().trim());
        return n;
    }
    public static String[] takeStrings(BufferedReader br)throws IOException{
        String inp[]=br.readLine().trim().split(" ");
        return inp;
    }
    public static int[] takeInts(BufferedReader br)throws IOException{
        String inp[]=takeStrings(br);
        int n=inp.length;
        int arr[]=new int[n];
        for(int i=0;i<n;i++){
            arr[i]=Integer.parseInt(inp[i]);
        }
        return arr;
    }
    public static char[] generateStrings(char str[], int n, char dig){
       char strs[]=new char[n];
       for(int i=0;i<n;i++){
           if(str[i] == 'X') strs[i]=dig;
           else strs[i]=str[i];
       }
       return strs;
    }
    public static void main(String args[])throws IOException{
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        int test = 1;
        StringBuilder ans=new StringBuilder();
        outer:while(test-->0){

            char str[]=br.readLine().trim().toCharArray();
            int n=str.length;

            if(n == 1){
                if(str[0] == '0' || str[0] == '_' || str[0] == 'X' || str[0] == '1'){
                    ans.append(1+"\n");continue;
                }
            }

            long cnt=0;
            boolean Xp =false;
            // boolean allZero=true;
            // for(int i=0;i<n;i++) if(str[i] != '0') allZero=false;

            for(int i=0;i<n;i++) if(str[i] == 'X') Xp=true;

            if(Xp){
                for(char ch='0';ch<='9';ch++){
                    cnt+=solve(generateStrings(str, n, ch), n);
                }
            }
            else{
                cnt+=solve(str, n);
            }

            ans.append(cnt+"\n");
        }
        System.out.println(ans);
    }
    public static long cal(char str[], String suffix, int n, int un)
    {
        if(n<2) return 0;
        char last =suffix.charAt(1);
        char first=suffix.charAt(0);
        if(str[n-1] == '_' || str[n-1] == last){
            if(str[n-2] == '_' || str[n-2] == first ){
                return (long)Math.pow(10, un);
            }
        }

        return 0;
    }
    public static long solve(char str[], int n){
        if(n == 1 || str[0] == '0') return 0;
        long a=0,b=0,c=0,d=0;
        int un=0;
        for(int i=1;i<n-2;i++) if(str[i] == '_') ++un;
        long cnt=0;

        cnt+=cal(str, "25", n, un);
        cnt+=cal(str, "50", n, un);
        cnt+=cal(str, "75", n, un);

        if(n>2)
        if(str[0] == '_') cnt*=9l;

        // System.out.println(new String(str));

        if(n>=3)
        {
            if((str[n-1] == '_' || str[n-1] == '0') && (str[n-2] == '_' || str[n-2] == '0')){
                if(n>3)
                {
                    long temp=(long)Math.pow(10, un);
                    if(str[0] == '_') temp*=9l;
                    cnt+=temp;
                }
                else if(n == 3)
                {
                    // System.out.println("Entering...."+str[0]);
                    if(str[0] == '_'){
                        cnt+=9;
                        // System.out.println("Entered@"+cnt);
                    }
                    else{
                        cnt+=1;
                    }
                }
            }
        }

        // System.out.println(cnt);
        return cnt;
    }
}