You've got an n × m table (n rows and m columns), each cell of the table contains a "0" or a "1".

Your task is to calculate the number of rectangles with the sides that are parallel to the sides of the table and go along the cell borders, such that the number one occurs exactly k times in the rectangle. 

Input

The first line contains three space-separated integers n, m and k (1 ≤ n, m ≤ 2500, 0 ≤ k ≤ 6) — the sizes of the table and the required number of numbers one.

Next n lines each contains m characters "0" or "1". The i-th character of the j-th line corresponds to the character that is in the j-th row and the i-th column of the table.

Output

Print a single number — the number of rectangles that contain exactly k numbers one.

Please, do not write the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams or the %I64d specifier.

Examples

Input

3 3 2
101
000
101


Output

8


Input

5 5 1
00000
00000
00100
00000
00000


Output

81


Input

5 5 6
01010
10101
01010
10101
01010


Output

12


Input

3 3 0
001
010
000


Output

15


Input

4 4 0
0000
0101
0000
0000


Output

52
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Iterator;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Objects;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 29);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            FastOutput out = new FastOutput(outputStream);
            EEmptyRectangles solver = new EEmptyRectangles();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class EEmptyRectangles {
        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.ri();
            int m = in.ri();
            int k = in.ri();
            int[][] mat = new int[n][m];
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    mat[i][j] = in.rc() - '0';
                }
            }

            long ans = RectOnGridProblem.countExactlyKOneRect(mat, k);
            out.println(ans);

        }

    }

    static class LinkedListBeta<E> implements Iterable<E> {
        public LinkedListBeta.Node<E> dummy = new LinkedListBeta.Node<>(null);
        protected int size;

        public LinkedListBeta.Node<E> begin() {
            return dummy.next;
        }

        public LinkedListBeta.Node<E> end() {
            return dummy;
        }

        public LinkedListBeta.Node<E> addLast(E e) {
            LinkedListBeta.Node<E> node = new LinkedListBeta.Node<>(e);
            return addLast(node);
        }

        public LinkedListBeta.Node<E> addAfter(LinkedListBeta.Node<E> node, LinkedListBeta.Node<E> follow) {
            follow.attach(node);
            size++;
            return follow;
        }

        public LinkedListBeta.Node<E> addLast(LinkedListBeta.Node<E> node) {
            return addAfter(dummy.prev, node);
        }

        public void remove(LinkedListBeta.Node<E> node) {
            assert contain(node);
            node.detach();
            size--;
            assert size >= 0;
        }

        public boolean contain(LinkedListBeta.Node<E> node) {
            for (LinkedListBeta.Node<E> head = begin(); head != end(); head = head.next) {
                if (head == node) {
                    return true;
                }
            }
            return false;
        }

        public RevokeIterator<E> iterator() {
            return new RevokeIterator<E>() {
                LinkedListBeta.Node<E> trace = dummy;


                public void revoke() {
                    trace = trace.prev;
                }


                public boolean hasNext() {
                    return trace.next != dummy;
                }


                public E next() {
                    return (trace = trace.next).val;
                }
            };
        }

        public String toString() {
            StringBuilder ans = new StringBuilder("[");
            for (E e : this) {
                ans.append(e).append(',');
            }
            if (ans.length() > 1) {
                ans.setLength(ans.length() - 1);
            }
            ans.append(']');
            return ans.toString();
        }

        public static class Node<E> extends CircularLinkedNode<LinkedListBeta.Node<E>> {
            public E val;

            public Node(E val) {
                this.val = val;
            }

            public String toString() {
                return Objects.toString(val);
            }

        }

    }

    static interface RevokeIterator<E> extends Iterator<E> {
    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int ri() {
            return readInt();
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public char rc() {
            return readChar();
        }

        public char readChar() {
            skipBlank();
            char c = (char) next;
            next = read();
            return c;
        }

    }

    static interface IntegerIterator {
        boolean hasNext();

        int next();

    }

    static class RectOnGridProblem {
        public static long countExactlyKOneRect(int[][] mat, int k) {
            return new RectOnGridProblem.ExactlyKOneRectSovler().count(mat, k);
        }

        public static long[][] countAllZeroRect(Int2ToIntegerFunction mat, int n, int m) {
            long[][] tag = new long[n + 1][m + 1];
            int[] low = new int[m];
            boolean[] active = new boolean[m];
            int[] left = new int[m];
            int[] right = new int[m];
            Arrays.fill(low, n);
            LinkedListBeta<Integer> list = new LinkedListBeta<>();
            LinkedListBeta.Node<Integer>[] nodes = new LinkedListBeta.Node[m];
            for (int i = 0; i < m; i++) {
                nodes[i] = list.addLast(i);
            }
            for (int i = n - 1; i >= 0; i--) {
                for (int j = 0; j < m; j++) {
                    if (mat.apply(i, j) != 0) {
                        list.remove(nodes[j]);
                        list.addLast(nodes[j]);
                        low[j] = i;
                    }
                }
                Arrays.fill(active, false);
                for (int j : list) {
                    int row = low[j] - 1;
                    int high = row - i + 1;
                    active[j] = true;
                    int l = j;
                    int r = j;
                    tag[high][1]++;
                    while (l > 0 && active[l - 1]) {
                        //merge
                        int lr = l - 1;
                        int ll = left[lr];
                        tag[high][lr - ll + 1]--;
                        tag[high][r - l + 1]--;
                        l = ll;
                        tag[high][r - l + 1]++;
                    }
                    while (r + 1 < m && active[r + 1]) {
                        //merge
                        int rl = r + 1;
                        int rr = right[rl];
                        tag[high][rr - rl + 1]--;
                        tag[high][r - l + 1]--;
                        r = rr;
                        tag[high][r - l + 1]++;
                    }
                    left[l] = left[r] = l;
                    right[r] = right[l] = r;
                }
            }

            for (int i = n - 1; i >= 0; i--) {
                for (int j = 0; j <= m; j++) {
                    tag[i][j] += tag[i + 1][j];
                }
            }
            for (int i = 1; i <= n; i++) {
                long cc = 0;
                long last = 0;
                for (int j = m; j >= 0; j--) {
                    cc += tag[i][j];
                    last += cc;
                    tag[i][j] = last;
                }
            }

            for (int i = 0; i <= m; i++) {
                tag[0][i] = 0;
            }

            for (int i = 0; i <= n; i++) {
                tag[i][0] = 0;
            }

            return tag;
        }

        private static class ExactlyKOneRectSovler {
            int[] left;
            int[] right;
            int[] matchSize;
            long matchPair;
            int[] size;

            void add(int x, int sign) {
                assert size[x] > 0;
                matchPair += sign * (right[x] - left[x] + 1) * matchSize[x];
                assert matchPair >= 0;
            }

            public long count(int[][] mat, int k) {
                int n = mat.length;
                int m = mat[0].length;

                if (k == 0) {
                    long[][] res = countAllZeroRect((i, j) -> mat[i][j], n, m);
                    long ans = 0;
                    for (int i = 1; i <= n; i++) {
                        for (int j = 1; j <= m; j++) {
                            ans += res[i][j];
                        }
                    }

                    return ans;
                }

                int[][] next = new int[n + 1][m];
                Arrays.fill(next[n], n);
                for (int i = n - 1; i >= 0; i--) {
                    for (int j = 0; j < m; j++) {
                        next[i][j] = next[i + 1][j];
                        if (mat[i][j] == 1) {
                            next[i][j] = i;
                        }
                    }
                }

                IntegerMultiWayStack stack = new IntegerMultiWayStack(n, (m + 1) * k);
                size = new int[m + 1];
                left = new int[m + 1];
                right = new int[m + 1];
                matchSize = new int[m + 1];

                long ans = 0;
                for (int i = 0; i < n; i++) {
                    stack.clear();
                    Arrays.fill(size, 0);
                    size[m] = k + 1;
                    for (int j = 0; j < m; j++) {
                        int h = i;
                        while (size[j] <= k) {
                            h = next[h][j];
                            if (h >= n) {
                                break;
                            }
                            size[j]++;
                            stack.addLast(h, j);
                            h++;
                        }
                    }
                    int last = 0;
                    for (int j = 0; j <= m; j++) {
                        if (size[j] != 0) {
                            left[last] = left[j] = last;
                            right[last] = right[j] = j;
                            last = j + 1;
                        }
                    }
                    Arrays.fill(matchSize, 0);
                    int sum = 0;
                    int consider = right[0];
                    matchPair = 0;
                    for (int j = right[0]; j < m; j = right[j + 1]) {
                        if (consider < j) {
                            consider = j;
                            sum = 0;
                        }
                        while (sum + size[consider] <= k) {
                            sum += size[consider];
                            consider = right[consider + 1];
                        }
                        if (sum == k) {
                            matchSize[j] = right[consider] - left[consider] + 1;
                        } else {
                            matchSize[j] = 0;
                        }
                        add(j, 1);
                        sum -= size[j];
                    }

                    long contrib = 0;
                    for (int j = n - 1; j >= i; j--) {
                        contrib += matchPair;
                        while (!stack.isEmpty(j)) {
                            int head = stack.removeLast(j);
                            add(head, -1);
                            size[head]--;

                            int end = head;
                            if (size[head] == 0) {
                                int leftPart = left[head];
                                int rightPart = right[head + 1];
                                add(rightPart, -1);
                                end = rightPart;
                                left[leftPart] = left[rightPart] = leftPart;
                                right[leftPart] = right[rightPart] = rightPart;
                            }
                            //from last k
                            int begin = end;
                            for (int step = 0; left[begin] > 0 && step < k; step++) {
                                begin = left[begin] - 1;
                                assert size[begin] > 0;
                                add(begin, -1);
                            }

                            sum = 0;
                            consider = -1;
                            while (begin < m && begin <= end) {
                                if (consider < begin) {
                                    consider = begin;
                                    sum = 0;
                                }
                                while (sum + size[consider] <= k) {
                                    sum += size[consider];
                                    consider = right[consider + 1];
                                }
                                if (sum == k) {
                                    matchSize[begin] = right[consider] - left[consider] + 1;
                                } else {
                                    matchSize[begin] = 0;
                                }
                                add(begin, 1);
                                sum -= size[begin];
                                begin = right[begin + 1];
                            }
                        }
                    }
                    ans += contrib;
                }

                return ans;
            }

        }

    }

    static interface Int2ToIntegerFunction {
        int apply(int a, int b);

    }

    static class CircularLinkedNode<T extends CircularLinkedNode<T>> {
        public T prev = (T) this;
        public T next = (T) this;

        public void attach(T node) {
            this.next = node.next;
            this.prev = node;
            this.next.prev = (T) this;
            this.prev.next = (T) this;
        }

        public void detach() {
            this.prev.next = next;
            this.next.prev = prev;
            this.next = this.prev = (T) this;
        }

    }

    static class FastOutput implements AutoCloseable, Closeable, Appendable {
        private static final int THRESHOLD = 32 << 10;
        private final Writer os;
        private StringBuilder cache = new StringBuilder(THRESHOLD * 2);

        public FastOutput append(CharSequence csq) {
            cache.append(csq);
            return this;
        }

        public FastOutput append(CharSequence csq, int start, int end) {
            cache.append(csq, start, end);
            return this;
        }

        private void afterWrite() {
            if (cache.length() < THRESHOLD) {
                return;
            }
            flush();
        }

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput append(char c) {
            cache.append(c);
            afterWrite();
            return this;
        }

        public FastOutput append(long c) {
            cache.append(c);
            afterWrite();
            return this;
        }

        public FastOutput println(long c) {
            return append(c).println();
        }

        public FastOutput println() {
            return append('\n');
        }

        public FastOutput flush() {
            try {
//            boolean success = false;
//            if (stringBuilderValueField != null) {
//                try {
//                    char[] value = (char[]) stringBuilderValueField.get(cache);
//                    os.write(value, 0, cache.length());
//                    success = true;
//                } catch (Exception e) {
//                }
//            }
//            if (!success) {
                os.append(cache);
//            }
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }

    static class IntegerMultiWayStack {
        private int[] values;
        private int[] next;
        private int[] heads;
        private int alloc;
        private int stackNum;

        public IntegerIterator iterator(final int queue) {
            return new IntegerIterator() {
                int ele = heads[queue];


                public boolean hasNext() {
                    return ele != 0;
                }


                public int next() {
                    int ans = values[ele];
                    ele = next[ele];
                    return ans;
                }
            };
        }

        private void doubleCapacity() {
            int newSize = Math.max(next.length + 10, next.length * 2);
            next = Arrays.copyOf(next, newSize);
            values = Arrays.copyOf(values, newSize);
        }

        public void alloc() {
            alloc++;
            if (alloc >= next.length) {
                doubleCapacity();
            }
            next[alloc] = 0;
        }

        public void clear() {
            alloc = 0;
            Arrays.fill(heads, 0, stackNum, 0);
        }

        public boolean isEmpty(int qId) {
            return heads[qId] == 0;
        }

        public IntegerMultiWayStack(int qNum, int totalCapacity) {
            values = new int[totalCapacity + 1];
            next = new int[totalCapacity + 1];
            heads = new int[qNum];
            stackNum = qNum;
        }

        public void addLast(int qId, int x) {
            alloc();
            values[alloc] = x;
            next[alloc] = heads[qId];
            heads[qId] = alloc;
        }

        public int removeLast(int qId) {
            int ans = values[heads[qId]];
            heads[qId] = next[heads[qId]];
            return ans;
        }

        public String toString() {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < stackNum; i++) {
                if (isEmpty(i)) {
                    continue;
                }
                builder.append(i).append(": ");
                for (IntegerIterator iterator = iterator(i); iterator.hasNext(); ) {
                    builder.append(iterator.next()).append(",");
                }
                if (builder.charAt(builder.length() - 1) == ',') {
                    builder.setLength(builder.length() - 1);
                }
                builder.append('\n');
            }
            return builder.toString();
        }

    }
}

