import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.TreeSet;
import java.util.TreeMap;

import static java.lang.Math.abs;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.Math.sqrt;
import static java.util.Arrays.copyOf;
import static java.util.Arrays.fill;
import static java.util.Arrays.sort;
import static java.util.Collections.reverse;
import static java.util.Collections.reverseOrder;
import static java.util.Collections.sort;

public class Main {
    private FastScanner in;
    private PrintWriter out;

    private void solve() throws IOException {
        solveC();
    }

    private void solveA() throws IOException {
        HashSet<Character> set = new HashSet<>();
        for (char c : new char[]{'a', 'e', 'i', 'o', 'u', '1', '3', '5', '7', '9'})
            set.add(c);
        int cnt = 0;
        for (char c : in.nextLine().toCharArray())
            if (set.contains(c))
                cnt++;
        out.println(cnt);
    }

    int n, m, cl;
    char a[][];
    int[] b;
    int fromi, fromj, toi, toj;

    private void solveB() throws IOException {
        n = in.nextInt();
        m = in.nextInt();
        char[] c;
        a = new char[n][m];
        for (int i = 0; i < n; i++) {
            a[i] = in.next().toCharArray();
        }

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (a[i][j] == 'S') {
                    fromi = i;
                    fromj = j;
                }
                if (a[i][j] == 'E') {
                    toi = i;
                    toj = j;
                }
            }
        }

        c = in.next().toCharArray();
        cl = c.length;
        b = new int[cl];
        for (int i = 0; i < cl; i++) {
            b[i] = c[i] - '0';
        }

        ArrayList<Long> ar1 = new ArrayList<>(), ar2 = new ArrayList<>(), ar3 = new ArrayList<>(), ar4 = new ArrayList<>();
        ar1.add((long) 12);
        ar1.add((long) 10);
        ar1.add((long) 01);
        ar1.add((long) 21);
        long[] str = new long[4];
        int ans = 0;
        for (long i : ar1) {
            str[0] = i;
            ar2.clear();
            ar2.addAll(ar1);
            ar2.remove(i);

            for (long j : ar2) {
                str[1] = j;
                ar3.clear();
                ar3.addAll(ar2);
                ar3.remove(j);

                for (long k : ar3) {
                    str[2] = k;
                    ar4.clear();
                    ar4.addAll(ar3);
                    ar4.remove(k);

                    str[3] = ar4.get(0);
                    if (bfs(str))
                        ans++;
                }
            }
        }
        out.println(ans);
    }

    private boolean bfs(long[] str) {
        int[][] steps = {{(int) str[0] / 10 - 1, (int) str[0] % 10 - 1},
                {(int) str[1] / 10 - 1, (int) str[1] % 10 - 1},
                {(int) str[2] / 10 - 1, (int) str[2] % 10 - 1},
                {(int) str[3] / 10 - 1, (int) str[3] % 10 - 1}};

        for (int i = 0, ci = fromi, cj = fromj; i < cl; i++) {
            ci += steps[b[i]][0];
            cj += steps[b[i]][1];

            if (ci >= n || ci < 0 || cj >= m || cj < 0 || a[ci][cj] == '#')
                return false;

            if (a[ci][cj] == 'E')
                return true;
        }

        return false;
    }

    private void solveC() throws IOException {
        int n = in.nextInt();
        int r = in.nextInt();
        int[] x = new int[n];
        for (int i = 0; i < n; i++) {
            x[i] = in.nextInt();
        }

        double[] y = new double[n];
        for (int i = 0; i < n; i++) {
            y[i] = r;
            for (int j = 0; j < i; j++) {
                if (abs(x[i] - x[j]) <= 2 * r) {
                    y[i] = max(y[i], y[j] + sqrt(4.0 * r * r - (x[i] - x[j]) * (x[i] - x[j])));
                }
            }
        }

        for (double ty : y)
            out.print(ty + " ");
        out.println();

    }

    private void solveD() throws IOException {

    }

    private void solveE() throws IOException {

    }

    private void solveF() throws IOException {

    }

    class FastScanner {
        StringTokenizer st;
        BufferedReader br;

        FastScanner(InputStream s) {
            br = new BufferedReader(new InputStreamReader(s));
        }

        String next() throws IOException {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        boolean hasNext() throws IOException {
            return br.ready() || (st != null && st.hasMoreTokens());
        }

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

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

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

        String nextLine() throws IOException {
            return br.readLine();
        }

        boolean hasNextLine() throws IOException {
            return br.ready();
        }
    }

    private void run() throws IOException {
        in = new FastScanner(System.in); // new FastScanner(new FileInputStream(".in"));
        out = new PrintWriter(System.out); // new PrintWriter(new FileOutputStream(".out"));

        solve();

        out.flush();
        out.close();
    }

    public static void main(String[] args) throws IOException {
        new Main().run();
    }
}


//package info.stochastic;

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

public class C {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskC solver = new TaskC();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskC {

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int r = in.nextInt();

            int x[] = new int[n];
            for (int i = 0; i < n; i++) {
                x[i] = in.nextInt();
            }

            double ans[] = new double[n];
            ans[0] = r;
            int index = 1;

            for (int i = 1; i < n; i++) {
                double maxY = r;
                for (int j = 0; j < index; j++) {
                    int xDist = Math.abs(x[i] - x[j]);
                    if (xDist <= r * 2) {
                        double cur = Math.sqrt((r * 2)*(r * 2) - xDist * xDist) + ans[j];
                        //out.println(cur);
                        maxY = Math.max(maxY, cur);
                    }
                }
                //out.println();
                ans[i] = maxY;
                index++;
            }

            for (int i = 0; i < n; i++) {
                out.print(ans[i] + " ");
            }

        }
    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

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


//package codeforces;

import java.util.Scanner;

public class Fingerprints {

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);

		int[] code = new int[scanner.nextInt()];
		int[] prints = new int[scanner.nextInt()];

		for (int i = 0; i < code.length; i++) {
			code[i] = scanner.nextInt();
		}
		for (int i = 0; i < prints.length; i++) {
			prints[i] = scanner.nextInt();
		}
		for (int i = 0; i < code.length; i++) {
			for (int j = 0; j < prints.length; j++) {
				if (code[i] == prints[j]) {
					System.out.print(prints[j] + " ");
				}
			}
		}
		scanner.close();
	}

}


/**
 * Created by Baelish on 8/28/2018.
 */

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class F_DSU {
    public static void main(String[] args)throws Exception {
        FastReader in = new FastReader(System.in);
        PrintWriter pw = new PrintWriter(System.out);
        n = in.nextInt();

        int brr[] = new int[2*n];
        for (int i = 0; i < 2*n; i+= 2) {
            brr[i] = in.nextInt();
            brr[i+1] = in.nextInt();
        }

        arr = shrink(brr);
        int imap[] = new int[2*n];
        for (int i = 0; i < 2*n; i++) {
            imap[arr[i]] = brr[i];
        }

        int idx = binarySearch(arr.length);
        if(idx >= arr.length) pw.println(-1);
        else pw.println(imap[idx]);

        pw.close();
    }
    static int n, arr[];

    static int binarySearch(int H) {
        int lo = 0, hi = H, mid;
        while (lo < hi) {
            mid = (lo + hi) / 2;
            if (check(mid)) hi = mid;
            else lo = mid + 1;
        }
        if(lo > 0 && check(lo-1)) return lo-1;
        return lo;
    }

    static boolean check(int m){
        DSU dsu = new DSU(2*n);
        for (int i = 0; i < n; i++) {
            int u = arr[2*i], v = arr[2*i+1];
            if(u > m) return false;
            if(v > m){
                if(++dsu.cycle[dsu.find(u)] >= 2) return false;
            }
            else{
                if(!dsu.union(u, v)){
                    if(++dsu.cycle[dsu.find(u)] >= 2) return false;
                }
                else{
                    if(dsu.cycle[dsu.find(u)] >= 2) return false;
                }
            }
        }
        return true;
    }

    static class DSU{
        int parent[], cycle[], n;
        DSU(int N){
            n = N;
            parent = new int[N];
            cycle = new int[N];
            for(int i = 0; i < N; i++){
                parent[i] = i;
            }
        }

        DSU(int [] p){
            parent = p; n = p.length;
        }

        int find(int i) {
            int p = parent[i];
            if (i == p) return i;
            return parent[i] = find(p);
        }

        boolean equiv(int u, int v){
            return find(u) == find(v);
        }

        boolean union(int u, int v){
            u = find(u); v = find(v);
            if(u != v) {
                parent[u] = parent[v];
                cycle[v] += cycle[u];
            }
            return u != v;
        }

        int count(){
            int cnt = 0;
            for(int i = 0; i < n; i++){
                if(i == find(i)) cnt++;
            }
            return cnt;
        }
    }

    public static int[] shrink(int[] a) {
        int n = a.length;
        long[] b = new long[n];
        for(int i = 0;i < n;i++)b[i] = (long)a[i]<<32|i;
        Arrays.sort(b);
        int[] ret = new int[n];
        int p = 0;
        for(int i = 0;i < n;i++) {
            if(i>0 && (b[i]^b[i-1])>>32!=0)p++;
            ret[(int)b[i]] = p;
        }
        return ret;
    }

    static void debug(Object...obj) {
        System.err.println(Arrays.deepToString(obj));
    }

    static class FastReader {
        InputStream is;
        private byte[] inbuf = new byte[1024];
        private int lenbuf = 0, ptrbuf = 0;
        static final int ints[] = new int[128];

        public FastReader(InputStream is){
            for(int i='0';i<='9';i++) ints[i]=i-'0';
            this.is = is;
        }

        public 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++];
        }

        public boolean isSpaceChar(int c) {
            return !(c >= 33 && c <= 126);
        }
        public int skip() {
            int b;
            while((b = readByte()) != -1 && isSpaceChar(b));
            return b;
        }

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

        public int nextInt(){
            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<<3) + (num<<1) + ints[b];
                }else{
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        public long nextLong() {
            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<<3) + (num<<1) + ints[b];
                }else{
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }
       /* public char nextChar() {
            return (char)skip();
        }*/

        public char[] next(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 buff[] = new char[1005];
        public char[] nextCharArray(){
            int b = skip(), p = 0;
            while(!(isSpaceChar(b))){
                buff[p++] = (char)b;
                b = readByte();
            }
            return Arrays.copyOf(buff, p);
        }*/
    }
}


import java.util.Scanner;

public class FUck {

		public static void main(String args[])
		{
			Scanner scan=new Scanner(System.in);
			int n=scan.nextInt();
			int k=scan.nextInt();
			String t=scan.next();
			int mx=0;
			for(int i=1;i<n;i++)
			{
				int gd=1;
				for(int j=0;j<i;j++)
				{

					if(t.charAt(j)!=t.charAt((n-i)+j))
					{

						gd=0;
						// i think i can break here
					}
					}
				if(gd==1){
					mx=i;

				}
			}
			System.out.print(t);
			for(int i=2;i<=k;i++)
			{
				for(int j=mx;j<n;j++)
				{
					System.out.print(t.charAt(j));
				}
			}
		}
}


import java.util.*;
public class TestClass
{
   public static void main(String args[])
   {
   	Scanner in = new Scanner(System.in);
   	int n = in.nextInt();
   	int m = in.nextInt();
   	int k = in.nextInt();
   	int arr[] = new int[n+1];
   	for(int i =0;i<n;i++)
   	 arr[i+1]= in.nextInt();

   	long sum[] = new long [n+1];

   	for(int i=1;i<=n;i++)
   	 sum[i]=sum[i-1]+arr[i];

    long dp[] = new long[n+1];

    for(int i =1;i<=n;i++)
    {
      for(int j=i;j>i-m&&j>=1;j--)
      {
        long val = sum[i]-sum[j-1]+dp[j-1]-k;
        dp[i]= Math.max(dp[i],val);
      }
    }
    long max =0;
    for(int i =1;i<=n;i++)
     max=Math.max(max,dp[i]);

    System.out.println(max);

   }
}


import java.util.*;

import javax.lang.model.util.ElementScanner6;

import java.io.*;

public class Main {

    public static void main(String[] args) {

        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader inp = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Solver solver = new Solver();
        solver.solve(inp, out);
        out.close();

    }

    static class Solver {

        class pair implements Comparable<pair>{

            int i;
            long dist;
            public pair(int i,long dist)
            {
                this.i=i;
                this.dist=dist;
            }

            public int compareTo(pair p)
            {
                return Long.compare(this.dist,p.dist);
            }

        }

        class Node implements Comparable < Node > {
            int i;
            int cnt;

            Node(int i, int cnt) {
                this.i = i;
                this.cnt = cnt;
            }

            public int compareTo(Node n) {
                if (this.cnt == n.cnt) {
                    return Integer.compare(this.i, n.i);
                }
                return Integer.compare(this.cnt, n.cnt);
            }
        }

        public boolean done(int[] sp, int[] par) {
            int root;

            root = findSet(sp[0], par);

            for (int i = 1; i < sp.length; i++) {
                if (root != findSet(sp[i], par))
                    return false;
            }
            return true;
        }
        public int findSet(int i, int[] par) {
            int x = i;
            boolean flag = false;
            while (par[i] >= 0) {
                flag = true;
                i = par[i];
            }
            if (flag)
                par[x] = i;
            return i;
        }

        public void unionSet(int i, int j, int[] par) {
            int x = findSet(i, par);
            int y = findSet(j, par);
            if (x < y) {
                par[y] = x;
            } else {
                par[x] = y;
            }
        }

        public long pow(long a, long b, long MOD) {
            if (b == 0) {
                return 1;
            }
            if (b == 1) {
                return a;
            }
            long val = pow(a, b / 2, MOD);
            if (b % 2 == 0) {
                return val * val % MOD;
            } else {
                return val * (val * a % MOD) % MOD;

            }

        }

        public boolean isPrime(int n)
        {
            for(int i=2;i<n;i++)
            {
                if(n%i==0)
                {
                    return false;
                }
            }
            return true;
        }

        public void minPrimeFactor(int n, int[] s) {
            boolean prime[] = new boolean[n + 1];
            Arrays.fill(prime, true);
            s[1] = 1;
            s[2] = 2;
            for (int i = 4; i <= n; i += 2) {
                prime[i] = false;
                s[i] = 2;
            }

            for (int i = 3; i <= n; i += 2) {
                if (prime[i]) {
                    s[i] = i;
                    for (int j = 2 * i; j <= n; j += i) {
                        prime[j] = false;
                        s[j] = i;
                    }
                }
            }

        }

        public void findAllPrime(int n, ArrayList < Node > al, int s[]) {
            int curr = s[n];
            int cnt = 1;
            while (n > 1) {
                n /= s[n];
                if (curr == s[n]) {
                    cnt++;
                    continue;

                }
                Node n1 = new Node(curr, cnt);
                al.add(n1);

                curr = s[n];
                cnt = 1;
            }
        }

        public int binarySearch(int n, int k) {
            int left = 1;
            int right = 100000000 + 5;
            int ans = 0;
            while (left <= right) {
                int mid = (left + right) / 2;
                if (n / mid >= k) {
                    left = mid + 1;
                    ans = mid;
                } else {
                    right = mid - 1;
                }
            }

            return ans;
        }
        public boolean checkPallindrom(String s) {
            char ch[] = s.toCharArray();

            for (int i = 0; i < s.length() / 2; i++) {
                if (ch[i] != ch[s.length() - 1 - i])
                    return false;
            }
            return true;
        }

        public void remove(ArrayList < Integer > [] al, int x) {
            for (int i = 0; i < al.length; i++) {
                for (int j = 0; j < al[i].size(); j++) {

                    if (al[i].get(j) == x)
                        al[i].remove(j);

                }
            }
        }

        public long gcd(long a, long b) {
            if (a == 0)
                return b;
            return gcd(b % a, a);
        }

        public void printDivisors(long n, ArrayList < Long > al) {
            // Note that this loop runs till square root
            for (long i = 1; i <= Math.sqrt(n); i++) {
                if (n % i == 0) {
                    // If divisors are equal, print only one
                    if (n / i == i) {
                        al.add(i);
                    } else // Otherwise print both
                    {
                        al.add(i);
                        al.add(n / i);
                    }

                }
            }
        }

        public static long constructSegment(long seg[], long arr[], int low, int high, int pos) {
            if (low == high) {
                seg[pos] = arr[low];
                return seg[pos];
            }
            int mid = (low + high) / 2;
            long t1 = constructSegment(seg, arr, low, mid, (2 * pos) + 1);
            long t2 = constructSegment(seg, arr, mid + 1, high, (2 * pos) + 2);
            seg[pos] = t1 + t2;
            return seg[pos];

        }
        public static long querySegment(long seg[], int low, int high, int qlow, int qhigh, int pos) {

            if (qlow <= low && qhigh >= high) {
                return seg[pos];
            } else if (qlow > high || qhigh < low) {
                return 0;
            } else {
                long ans = 0;
                int mid = (low + high) / 2;
                ans += querySegment(seg, low, mid, qlow, qhigh, (2 * pos) + 1);
                ans += querySegment(seg, mid + 1, high, qlow, qhigh, (2 * pos) + 2);
                return ans;
            }

        }
        public static int lcs(char[] X, char[] Y, int m, int n) {
            if (m == 0 || n == 0)
                return 0;
            if (X[m - 1] == Y[n - 1])
                return 1 + lcs(X, Y, m - 1, n - 1);
            else
                return Integer.max(lcs(X, Y, m, n - 1), lcs(X, Y, m - 1, n));
        }

        public static long recursion(long start, long end, long cnt[], int a, int b) {

            long min = 0;
            long count = 0;
            int ans1 = -1;
            int ans2 = -1;
            int l = 0;
            int r = cnt.length - 1;
            while (l <= r) {
                int mid = (l + r) / 2;
                if (cnt[mid] >= start) {
                    ans1 = mid;
                    r = mid - 1;
                } else {
                    l = mid + 1;
                }
            }

            l = 0;
            r = cnt.length - 1;
            while (l <= r) {
                int mid = (l + r) / 2;
                if (cnt[mid] <= end) {
                    ans2 = mid;
                    l = mid + 1;
                } else {
                    r = mid - 1;
                }
            }

            if (ans1 == -1 || ans2 == -1 || ans2 < ans1) {
                // System.out.println("min1 "+min);
                min = a;
                return a;

            } else {
                min = b * (end - start + 1) * (ans2 - ans1 + 1);
            }
            if (start == end) {
                // System.out.println("min "+min);
                return min;
            }
            long mid = (end + start) / 2;
            min = Long.min(min, recursion(start, mid, cnt, a, b) + recursion(mid + 1, end, cnt, a, b));
            // System.out.println("min "+min);
            return min;
        }

        public int dfs_util(ArrayList < Integer > [] al, boolean vis[], int x, int[] s, int lvl[]) {

            vis[x] = true;
            int cnt = 1;
            for (int i = 0; i < al[x].size(); i++) {

                if (!vis[al[x].get(i)]) {
                    lvl[al[x].get(i)] = lvl[x] + 1;
                    cnt += dfs_util(al, vis, al[x].get(i), s, lvl);

                }

            }
            s[x] = cnt;
            return s[x];
        }

        public void dfs(ArrayList[] al, int[] s, int[] lvl) {

            boolean vis[] = new boolean[al.length];
            for (int i = 0; i < al.length; i++) {
                if (!vis[i]) {
                    lvl[i] = 1;
                    dfs_util(al, vis, i, s, lvl);
                }
            }
        }

        public int[] computeLps(String s)
        {
            int ans[] =new int[s.length()];
            char ch[] = s.toCharArray();
            int n = s.length();
            int i=1;
            int len=0;
            ans[0]=0;
            while(i<n)
            {
                if(ch[i]==ch[len])
                {
                    len++;
                    ans[i]=len;
                    i++;
                }
                else
                {
                    if(len!=0)
                    {
                        len=ans[len-1];
                    }
                    else
                    {
                        ans[i]=len;
                        i++;
                    }
                }
            }

            return ans;

        }

        private void solve(InputReader inp, PrintWriter out1) {
            int n = inp.nextInt();
            int m = inp.nextInt();
            long k = inp.nextLong();
            long arr[] = new long[n];

            for(int i=0;i<n;i++)
            {
                arr[i] = inp.nextLong();

            }
            long ans=0;
            for(int i=0;i<m;i++)
            {
                long sum=0;
                for(int j=i;j<n;j++)
                {

                    if(j%m==i)
                    {
                        if(sum<0)
                        {
                           sum=0;
                        }
                        sum-=k;
                    }

                    sum+=arr[j];

                    ans=Math.max(ans,sum);
                }

            }

            System.out.println(ans);

        }

}

    static class InputReader {
        BufferedReader reader;
        StringTokenizer tokenizer;

        InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

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

        public long nextLong() {
            return Long.parseLong(next());
        }
    }
}
class ele implements Comparable < ele > {
    int value;
    int i;
    boolean flag;
    public ele(int value, int i) {
        this.value = value;
        this.i = i;
        this.flag = false;
    }
    public int compareTo(ele e) {
        return Integer.compare(this.value, e.value);
    }
}


import java.util.*;
import java.math.*;
public class Solution{
    private long [] sums;
    private void solve(){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int k = sc.nextInt();
        int [] arr = new int[n];
        this.sums = new long[n];
        for(int i = 0; i < n; i++){
            arr[i] = sc.nextInt();
            sums[i] = arr[i] + (i == 0 ? 0 : sums[i - 1]);
        }
        long ans = 0;
        for(int i = 1; i <= n && i <= m; i++){
            ans = Math.max(ans, sum(0, i - 1) - k);
        }
        long [] dp = new long[n];
        for(int i = 0; i < n; i++){
            if(i + 1 >= m){
                long cur = sum(i - m + 1, i) - k;
                if(i - m >= 0){
                    cur += dp[i - m];
                }
                dp[i] = Math.max(dp[i], cur);
            }
            for(int j = 0; j <= m && i + j < n; j++){
                ans = Math.max(ans, dp[i] + sum(i + 1, i + j) - k * (j > 0 ? 1 : 0));
            }
        }
        System.out.println(ans);
    }
    private long sum(int l, int r){
        if(l <= 0){
            return sums[r];
        }else{
            return sums[r] - sums[l - 1];
        }
    }
    public static void main(String [] args){
        new Solution().solve();
    }
}


//package ContestEd69;

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

public class mainD {
    public static PrintWriter out = new PrintWriter(System.out);
    public static FastScanner enter = new FastScanner(System.in);
    public static long[] arr;
    public static void main(String[] args) throws IOException {
        int n=enter.nextInt();
        int m=enter.nextInt();
        long k=enter.nextLong();
        arr=new long[n+1];
        for (int i = 1; i <n+1 ; i++) {
            arr[i]=enter.nextLong();
        }
        long[] summ=new long[n+1];
        for (int i = 1; i <n+1 ; i++) {
            summ[i]+=arr[i]+summ[i-1];
        }

        long[] best=new long[n+1];

        for (int i = 1; i <n+1 ; i++) {
            best[i]=Math.max(0, ((i-m>=0) ? best[i-m]+summ[i]-summ[i-m]-k:0));
        }
        long ans=best[1];

        for (int i = 1; i <n+1 ; i++) {
            ans=Math.max(ans,best[i]);
            for (int j = 1; j <m ; j++) {
                ans=Math.max(ans, ((i-j>=0) ? best[i-j] -k +summ[i]-summ[i-j]:0));
            }
        }
        System.out.println(ans);
    }

    static class FastScanner {
        BufferedReader br;
        StringTokenizer stok;

        FastScanner(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        String next() throws IOException {
            while (stok == null || !stok.hasMoreTokens()) {
                String s = br.readLine();
                if (s == null) {
                    return null;
                }
                stok = new StringTokenizer(s);
            }
            return stok.nextToken();
        }

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

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

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

        char nextChar() throws IOException {
            return (char) (br.read());
        }

        String nextLine() throws IOException {
            return br.readLine();
        }
    }
}


//package goodbye2017;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

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

	void solve()
	{
		char[] s = ns().toCharArray();
		int mod = 1000000007;
		int m = 702;

		long[] bases = new long[m+1];
		bases[0] = 1;
		for(int i = 1;i <= m;i++)bases[i] = bases[i-1] * 10 % mod;

		// 10*700^3*10
		long ans = 0;
		for(int d = 9;d >= 1;d--){
			int n = s.length;
			long[] sum = new long[m]; // base
			long[] num = new long[m]; // base
			long esum = 0;
			int ebase = 0;
			for(int i = 0;i < n;i++){
				long[] nsum = new long[m]; // base
				long[] nnum = new long[m]; // base
				for(int j = 0;j < m;j++){
					for(int k = 0;k <= 9;k++){
						if(k > d && j+1 < m){
							nsum[j+1] += sum[j] * 10;
							nsum[j+1] %= mod;
							nnum[j+1] += num[j];
							if(nnum[j+1] >= mod)nnum[j+1] -= mod;
						}
						if(k == d){
							nsum[j] += sum[j] * 10 + num[j] * bases[j];
							nsum[j] %= mod;
							nnum[j] += num[j];
							if(nnum[j] >= mod)nnum[j] -= mod;
						}
						if(k < d){
							nsum[j] += sum[j];
							if(nsum[j] >= mod)nsum[j] -= mod;
							nnum[j] += num[j];
							if(nnum[j] >= mod)nnum[j] -= mod;
						}
					}
				}

				for(int k = 0;k < s[i]-'0';k++){
					if(k > d){
						nsum[ebase+1] += esum * 10;
						nsum[ebase+1] %= mod;
						nnum[ebase+1] += 1;
						if(nnum[ebase+1] >= mod)nnum[ebase+1] -= mod;
					}
					if(k == d){
						nsum[ebase] += esum * 10 + bases[ebase];
						nsum[ebase] %= mod;
						nnum[ebase] += 1;
						if(nnum[ebase] >= mod)nnum[ebase] -= mod;
					}
					if(k < d){
						nsum[ebase] += esum;
						if(nsum[ebase] >= mod)nsum[ebase] -= mod;
						nnum[ebase] += 1;
						if(nnum[ebase] >= mod)nnum[ebase] -= mod;
					}
				}

				if(s[i]-'0' > d){
					esum = esum * 10;
					esum %= mod;
					ebase++;
				}else if(s[i]-'0' == d){
					esum = esum * 10 + bases[ebase];
					esum %= mod;
				}

				sum = nsum;
				num = nnum;
			}
			long all = esum;
			for(int j = 0;j < m;j++){
				all += sum[j];
			}
			ans += all % mod * d;
		}
		out.println(ans%mod);
	}

	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 G().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)); }
}


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

public class MainG {
	static StdIn in = new StdIn();
	static PrintWriter out = new PrintWriter(System.out);
	static long M=(long)1e9+7;
	static int n, dig;
	static int[] x;
	static long[] p10, s;
	static long[][][] dp;

	public static void main(String[] args) {
		char[] cs = in.next().toCharArray();
		n=cs.length;
		x = new int[n];
		for(int i=0; i<n; ++i)
			x[i]=cs[i]-'0';
		p10 = new long[n];
		p10[0]=1;
		for(int i=1; i<n; ++i)
			p10[i]=p10[i-1]*10%M;
		s = new long[n+1];
		s[n]=1;
		for(int i=n-1; i>=0; --i)
			s[i]=(s[i+1]+x[i]*p10[n-1-i])%M;
		long ans=0;
		dp = new long[2][n][n+1];
		for(dig=1; dig<=9; ++dig) {
			for(int i=0; i<n; ++i) {
				Arrays.fill(dp[0][i], -1);
				Arrays.fill(dp[1][i], -1);
			}
			for(int i=1; i<=n; ++i)
				ans=(ans+p10[i-1]*dp(0, 0, i))%M;
		}
		out.println(ans);
		out.close();
	}

	static long dp(int less, int ignore, int need) {
		if(need==0)
			return less==1?p10[n-ignore]:s[ignore];
		if(ignore==n)
			return 0;
		if(dp[less][ignore][need]!=-1)
			return dp[less][ignore][need];
		long res=0;
		int lim=less==1?9:x[ignore];
		for(int i=0; i<=lim; ++i)
			res=(res+dp(less|(i<lim?1:0), ignore+1, need-(i>=dig?1:0)))%M;
		return dp[less][ignore][need]=res;
	}

	interface Input {
		public String next();
		public String nextLine();
		public int nextInt();
		public long nextLong();
		public double nextDouble();
	}
	static class StdIn implements Input {
		final private int BUFFER_SIZE = 1 << 16;
		private DataInputStream din;
		private byte[] buffer;
		private int bufferPointer, bytesRead;
		public StdIn() {
			din = new DataInputStream(System.in);
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}
		public StdIn(InputStream in) {
			try{
				din = new DataInputStream(in);
			} catch(Exception e) {
				throw new RuntimeException();
			}
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}
		public String next() {
			int c;
			while((c=read())!=-1&&(c==' '||c=='\n'||c=='\r'));
			StringBuilder s = new StringBuilder();
			while (c != -1)
			{
				if (c == ' ' || c == '\n'||c=='\r')
					break;
				s.append((char)c);
				c=read();
			}
			return s.toString();
		}
		public String nextLine() {
			int c;
			while((c=read())!=-1&&(c==' '||c=='\n'||c=='\r'));
			StringBuilder s = new StringBuilder();
			while (c != -1)
			{
				if (c == '\n'||c=='\r')
					break;
				s.append((char)c);
				c = read();
			}
			return s.toString();
		}
		public int nextInt() {
			int ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do
				ret = ret * 10 + c - '0';
			while ((c = read()) >= '0' && c <= '9');

			if (neg)
				return -ret;
			return ret;
		}
		public int[] readIntArray(int n) {
			int[] ar = new int[n];
			for(int i=0; i<n; ++i)
				ar[i]=nextInt();
			return ar;
		}
		public long nextLong() {
			long ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do
				ret = ret * 10 + c - '0';
			while ((c = read()) >= '0' && c <= '9');
			if (neg)
				return -ret;
			return ret;
		}
		public long[] readLongArray(int n) {
			long[] ar = new long[n];
			for(int i=0; i<n; ++i)
				ar[i]=nextLong();
			return ar;
		}
		public double nextDouble() {
			double ret = 0, div = 1;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do
				ret = ret * 10 + c - '0';
			while ((c = read()) >= '0' && c <= '9');
			if (c == '.')
				while ((c = read()) >= '0' && c <= '9')
					ret += (c - '0') / (div *= 10);
			if (neg)
				return -ret;
			return ret;
		}
		private void fillBuffer() throws IOException {
			bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
			if (bytesRead == -1)
				buffer[0] = -1;
		}
		private byte read() {
			try{
				if (bufferPointer == bytesRead)
					fillBuffer();
				return buffer[bufferPointer++];
			} catch(IOException e) {
				throw new RuntimeException();
			}
		}
		public void close() throws IOException {
			if (din == null)
				return;
			din.close();
		}
	}
}


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

public class G {

	static final int P = 1_000_000_007;

	int[][] ways;
	int[][] pow;

	void preCalc(int sz) {
		ways = new int[sz][];
		for (int i = 0; i < ways.length; i++) {
			ways[i] = new int[i + 1];
			ways[i][0] = ways[i][i] = 1;
			for (int j = 1; j < i; j++) {
				ways[i][j] = (ways[i - 1][j] + ways[i - 1][j - 1]) % P;
			}
		}

		pow = new int[10][sz];
		pow[0] = null;
		for (int i = 1; i <= 9; i++) {
			pow[i][0] = 1;
			for (int j = 1; j < sz; j++) {
				pow[i][j] = (int) ((long) pow[i][j - 1] * i % P);
			}
		}
	}

	int solve(String ss) {
		int n = ss.length();
		int[] s = new int[n];
		for (int i = 0; i < n; i++) {
			s[i] = ss.charAt(i) - '0';
		}

		preCalc(n + 10);

		int[] ans = new int[n + 1];

		int[] cnt = new int[10];

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

			int rest = n - i - 1;

			int dig = s[i];

			for (int j = 0; j <= (i == n - 1 ? dig : dig - 1); j++) {
				cnt[j]++; // now we have one more digit >= j

				for (int use = 1; use < 10; use++) {
					// use digits are bad, 10 - use are good
					for (int cntGood = 0; cntGood <= rest; cntGood++) {
						int delta = (int) ((long) ways[rest][cntGood]
								* pow[use][rest - cntGood] % P
								* pow[10 - use][cntGood] % P);
						int idx = cnt[use] + cntGood;
						ans[idx] += delta;
						if (ans[idx] >= P) {
							ans[idx] -= P;
						}
					}
				}

				// System.err.println(Arrays.toString(ans));

			}

			cnt[dig]++;

		}

		int ret = 0;
		long mult = 0;
		for (int i = 1; i < ans.length; i++) {
			mult = (10L * mult + 1) % P;
			ret += (int)(mult * ans[i] % P);
			if (ret >= P) {
				ret -= P;
			}
		}

		return ret;
	}

	void submit() {
		out.println(solve(nextToken()));
	}

	void stress() {

	}

	void test() {
		StringBuilder sb = new StringBuilder("1");
		for (int i = 0; i < 700; i++) {
			sb.append('0');
		}
		solve(sb.toString());
	}

	G() throws IOException {
		br = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		submit();
		// stress();
//		 test();
		out.close();
	}

	static final Random rng = new Random();

	static int rand(int l, int r) {
		return l + rng.nextInt(r - l + 1);
	}

	public static void main(String[] args) throws IOException {
		new G();
	}

	BufferedReader br;
	PrintWriter out;
	StringTokenizer st;

	String nextToken() {
		while (st == null || !st.hasMoreTokens()) {
			try {
				st = new StringTokenizer(br.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return st.nextToken();
	}

	String nextString() {
		try {
			return br.readLine();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

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

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

	double nextDouble() {
		return Double.parseDouble(nextToken());
	}
}


import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.lang.System.exit;

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

public class G {

	static final int MOD = 1000000007;

	static int add(int a, int b) {
		int res = a + b;
		return res >= MOD ? res - MOD : res;
	}

	static int sub(int a, int b) {
		int res = a - b;
		return res < 0 ? res + MOD : res;
	}

	static int mul(int a, int b) {
		int res = (int) ((long) a * b % MOD);
		return res < 0 ? res + MOD : res;
	}

	static int pow(int a, int e) {
		if (e == 0) {
			return 1;
		}
		int r = a;
		for (int i = 30 - Integer.numberOfLeadingZeros(e); i >= 0; i--) {
			r = mul(r, r);
			if ((e & (1 << i)) != 0) {
				r = mul(r, a);
			}
		}
		return r;
	}

	static int inv(int a) {
		return pow(a, MOD - 2);
	}

	static void solve() throws Exception {
		String x = scanString();
//		char xx[] = new char[700];
//		fill(xx, '9');
//		String x = new String(xx);
		int n = x.length();
		int pows[][] = new int[10][n];
		for (int i = 0; i < 10; i++) {
			pows[i][0] = 1;
			for (int j = 1; j < n; j++) {
				pows[i][j] = mul(pows[i][j - 1], i);
			}
		}
		int ru[] = new int[n + 1];
		for (int i = 1; i <= n; i++) {
			ru[i] = add(1, mul(10, ru[i - 1]));
		}
		int facts[] = new int[n];
		facts[0] = 1;
		for (int i = 1; i < n; i++) {
			facts[i] = mul(facts[i - 1], i);
		}
		int factsInv[] = new int[n];
		factsInv[n - 1] = inv(facts[n - 1]);
		for (int i = n - 1; i > 0; i--) {
			factsInv[i - 1] = mul(factsInv[i], i);
		}
		int ans = 0;
		int off[] = new int[10];
		for (int i = 0; i < n; i++) {
			int cd = x.charAt(i) - '0';
			int l = n - i - 1;
			for (int d = 1; d < 10; d++) {
				for (int p = 0; p <= l; p++) {
					int mul = d < cd ? add(mul(d, ru[p + off[d]]), mul(cd - d, ru[p + off[d] + 1])) : mul(cd, ru[p + off[d]]);
					ans = add(ans, mul(mul, mul(mul(pows[d][l - p], pows[10 - d][p]), mul(facts[l], mul(factsInv[p], factsInv[l - p])))));
				}
			}
			for (int d = 0; d <= cd; d++) {
				++off[d];
			}
		}
		for (int d = 1; d < 10; d++) {
			ans = add(ans, ru[off[d]]);
		}
		out.print(ans);
	}

	static int scanInt() throws IOException {
		return parseInt(scanString());
	}

	static long scanLong() throws IOException {
		return parseLong(scanString());
	}

	static String scanString() throws IOException {
		while (tok == null || !tok.hasMoreTokens()) {
			tok = new StringTokenizer(in.readLine());
		}
		return tok.nextToken();
	}

	static BufferedReader in;
	static PrintWriter out;
	static StringTokenizer tok;

	public static void main(String[] args) {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
			solve();
			in.close();
			out.close();
		} catch (Throwable e) {
			e.printStackTrace();
			exit(1);
		}
	}
}


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

public class MainG {
	static StdIn in = new StdIn();
	static PrintWriter out = new PrintWriter(System.out);
	static long M=(long)1e9+7;
	static int n, dig;
	static int[] x;
	static long[] p10, s;
	static long[][][] dp;

	public static void main(String[] args) {
		char[] cs = in.next().toCharArray();
		n=cs.length;
		x = new int[n];
		for(int i=0; i<n; ++i)
			x[i]=cs[i]-'0';
		p10 = new long[n];
		p10[0]=1;
		for(int i=1; i<n; ++i)
			p10[i]=p10[i-1]*10%M;
		s = new long[n+1];
		s[n]=1;
		for(int i=n-1; i>=0; --i)
			s[i]=(s[i+1]+x[i]*p10[n-1-i])%M;
		long ans=0;
		dp = new long[2][n][n+1];
		for(dig=1; dig<=9; ++dig) {
			for(int i=0; i<n; ++i) {
				Arrays.fill(dp[0][i], -1);
				Arrays.fill(dp[1][i], -1);
			}
			for(int i=1; i<=n; ++i)
				ans=(ans+p10[i-1]*dp(0, 0, i))%M;
		}
		out.println(ans);
		out.close();
	}

	static long dp(int less, int ignore, int need) {
		if(need==0)
			return less==1?p10[n-ignore]:s[ignore];
		if(ignore==n)
			return 0;
		if(dp[less][ignore][need]!=-1)
			return dp[less][ignore][need];
		long res=0;
		int lim=less==1?9:x[ignore];
		for(int i=0; i<=lim; ++i)
			res=(res+dp(less|(i<lim?1:0), ignore+1, need-(i>=dig?1:0)));
		res%=M;
		return dp[less][ignore][need]=res;
	}

	interface Input {
		public String next();
		public String nextLine();
		public int nextInt();
		public long nextLong();
		public double nextDouble();
	}
	static class StdIn implements Input {
		final private int BUFFER_SIZE = 1 << 16;
		private DataInputStream din;
		private byte[] buffer;
		private int bufferPointer, bytesRead;
		public StdIn() {
			din = new DataInputStream(System.in);
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}
		public StdIn(InputStream in) {
			try{
				din = new DataInputStream(in);
			} catch(Exception e) {
				throw new RuntimeException();
			}
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}
		public String next() {
			int c;
			while((c=read())!=-1&&(c==' '||c=='\n'||c=='\r'));
			StringBuilder s = new StringBuilder();
			while (c != -1)
			{
				if (c == ' ' || c == '\n'||c=='\r')
					break;
				s.append((char)c);
				c=read();
			}
			return s.toString();
		}
		public String nextLine() {
			int c;
			while((c=read())!=-1&&(c==' '||c=='\n'||c=='\r'));
			StringBuilder s = new StringBuilder();
			while (c != -1)
			{
				if (c == '\n'||c=='\r')
					break;
				s.append((char)c);
				c = read();
			}
			return s.toString();
		}
		public int nextInt() {
			int ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do
				ret = ret * 10 + c - '0';
			while ((c = read()) >= '0' && c <= '9');

			if (neg)
				return -ret;
			return ret;
		}
		public int[] readIntArray(int n) {
			int[] ar = new int[n];
			for(int i=0; i<n; ++i)
				ar[i]=nextInt();
			return ar;
		}
		public long nextLong() {
			long ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do
				ret = ret * 10 + c - '0';
			while ((c = read()) >= '0' && c <= '9');
			if (neg)
				return -ret;
			return ret;
		}
		public long[] readLongArray(int n) {
			long[] ar = new long[n];
			for(int i=0; i<n; ++i)
				ar[i]=nextLong();
			return ar;
		}
		public double nextDouble() {
			double ret = 0, div = 1;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do
				ret = ret * 10 + c - '0';
			while ((c = read()) >= '0' && c <= '9');
			if (c == '.')
				while ((c = read()) >= '0' && c <= '9')
					ret += (c - '0') / (div *= 10);
			if (neg)
				return -ret;
			return ret;
		}
		private void fillBuffer() throws IOException {
			bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
			if (bytesRead == -1)
				buffer[0] = -1;
		}
		private byte read() {
			try{
				if (bufferPointer == bytesRead)
					fillBuffer();
				return buffer[bufferPointer++];
			} catch(IOException e) {
				throw new RuntimeException();
			}
		}
		public void close() throws IOException {
			if (din == null)
				return;
			din.close();
		}
	}
}


import java.util.Arrays;
import java.util.Scanner;

public class Main {
    private static int REM = 1000000007;
    private static int dig;
    private static int[][][] dp = new int[701][701][2];

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        String X = in.next();
        int N = X.length();

        int[] P = new int[701];
        P[0] = 1;
        for (int i=1; i<P.length; ++i) {
            P[i] = (int)((long)P[i-1] * 10 % REM);
        }

        int ans = 0;
        for (int d=1; d<=9; ++d) { //at least d
            dig = d;

            for (int[][] array2 : dp) {
                for (int[] array1 : array2) {
                    Arrays.fill(array1, -1);
                }
            }

            for (int c=1; c<=N; ++c) { //exact count of at least d
                for (int k=0; k<c; ++k) {
                    ans = (int)((ans + (long)f(0, c, false, X) * P[k]) % REM);
                }
            }
        }
        System.out.println(ans);
    }

    private static int f(int ps, int needed, boolean less, final String X) {
        if (needed < 0) {return 0;}
        if (dp[ps][needed][less?0:1] != -1) {return dp[ps][needed][less?0:1];}
        if (ps == X.length()) {
            if (needed == 0) {return 1;}
            return 0;
        }
        int dg = X.charAt(ps)-'0';

        int ans = 0;
        for (int d=0; d<=9; ++d) {
            if (!less && d>dg) {continue;}

            boolean nless = less || d < dg;
            ans = (int)((ans + (long)f(ps+1, needed-(d>=dig?1:0), nless, X)) % REM);
        }

        dp[ps][needed][less?0:1] = ans;
        return ans;
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author Jialin Ouyang (Jialin.Ouyang@gmail.com)
 */
public class Main {
  public static void main(String[] args) {
    InputStream inputStream = System.in;
    OutputStream outputStream = System.out;
    QuickScanner in = new QuickScanner(inputStream);
    QuickWriter out = new QuickWriter(outputStream);
    TaskG solver = new TaskG();
    solver.solve(1, in, out);
    out.close();
  }

  static class TaskG {
    static int MAXL = 700 + 1;
    static IntModular MOD = new IntModular();
    int n;
    char[] digits;
    int[] pow10;
    int[] ones;
    int[][][] way;

    public void solve(int testNumber, QuickScanner in, QuickWriter out) {
      digits = new char[MAXL];
      n = in.next(digits);
      initPow();
      int res = MOD.mul(calc(9), 9);
      for (int digit = 0; digit < 9; ++digit) {
        res = MOD.sub(res, calc(digit));
      }
      out.println(res);
    }

    void initPow() {
      pow10 = new int[n + 1];
      ones = new int[n + 1];
      pow10[0] = 1;
      for (int i = 1; i <= n; ++i) {
        pow10[i] = MOD.mul(pow10[i - 1], 10);
        ones[i] = MOD.add(MOD.mul(ones[i - 1], 10), 1);
      }
    }

    int calc(int targetDigit) {
      if (way == null) {
        way = new int[2][2][n + 1];
      }
      int t = 0;
      clearCnt(t);
      way[t][0][0] = 1;
      for (int i = 0; i < n; ++i) {
        int digit = digits[i] - '0';
        clearCnt(t ^ 1);
        // not free
        for (int cnt = 0; cnt <= n; ++cnt)
          if (way[t][0][cnt] > 0) {
            // not free
            int newCnt = targetDigit < digit ? cnt + 1 : cnt;
            way[t ^ 1][0][newCnt] = MOD.add(
                way[t ^ 1][0][newCnt],
                way[t][0][cnt]);
            // free
            way[t ^ 1][1][cnt] = MOD.add(
                way[t ^ 1][1][cnt],
                MOD.mul(
                    Math.min(targetDigit + 1, digit),
                    way[t][0][cnt]));
            way[t ^ 1][1][cnt + 1] = MOD.add(
                way[t ^ 1][1][cnt + 1],
                MOD.mul(
                    Math.max(digit - targetDigit - 1, 0),
                    way[t][0][cnt]));
          }
        // free
        for (int cnt = 0; cnt <= n; ++cnt)
          if (way[t][1][cnt] > 0) {
            way[t ^ 1][1][cnt] = MOD.add(
                way[t ^ 1][1][cnt],
                MOD.mul(
                    targetDigit + 1,
                    way[t][1][cnt]));
            way[t ^ 1][1][cnt + 1] = MOD.add(
                way[t ^ 1][1][cnt + 1],
                MOD.mul(
                    9 - targetDigit,
                    way[t][1][cnt]));
          }
        t ^= 1;
      }
      int res = 0;
      for (int cnt = 0; cnt <= n; ++cnt) {
        res = MOD.add(
            res,
            MOD.mul(MOD.mul(
                ones[n - cnt],
                pow10[cnt]),
                MOD.add(way[t][0][cnt], way[t][1][cnt])));
      }
      return res;
    }

    void clearCnt(int t) {
      for (int free = 0; free < 2; ++free) {
        Arrays.fill(way[t][free], 0);
      }
    }

  }

  static class QuickWriter {
    private final PrintWriter writer;

    public QuickWriter(OutputStream outputStream) {
      this.writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
    }

    public QuickWriter(Writer writer) {
      this.writer = new PrintWriter(writer);
    }

    public void print(Object... objects) {
      for (int i = 0; i < objects.length; ++i) {
        if (i > 0) {
          writer.print(' ');
        }
        writer.print(objects[i]);
      }
    }

    public void println(Object... objects) {
      print(objects);
      writer.println();
    }

    public void close() {
      writer.close();
    }

  }

  static class IntModular {
    private static final int MOD = 1000000007;
    public final int mod;
    private final int[] x;

    public IntModular() {
      this(MOD);
    }

    public IntModular(int mod) {
      this.mod = mod;
      this.x = new int[2];
    }

    public int add(int a, int b) {
      return fix(a + b, mod);
    }

    public int sub(int a, int b) {
      return fix(a - b, mod);
    }

    public int mul(int a, int b) {
      return mul(a, b, mod);
    }

    public static int mul(int a, int b, int mod) {
      return a > 0
          ? (b < mod / a ? a * b : (int) ((long) a * b % mod))
          : 0;
    }

    public static int fix(int a, int mod) {
      a = slightFix(a, mod);
      return 0 <= a && a < mod ? a : slightFix(a % mod, mod);
    }

    private static int slightFix(int a, int mod) {
      return a >= mod
          ? a - mod
          : a < 0 ? a + mod : a;
    }

  }

  static class QuickScanner {
    private static final int BUFFER_SIZE = 1024;
    private InputStream stream;
    private byte[] buffer;
    private int currentPosition;
    private int numberOfChars;

    public QuickScanner(InputStream stream) {
      this.stream = stream;
      this.buffer = new byte[BUFFER_SIZE];
      this.currentPosition = 0;
      this.numberOfChars = 0;
    }

    public int next(char[] s) {
      return next(s, 0);
    }

    public int next(char[] s, int startIdx) {
      int b = nextNonSpaceChar();
      int res = 0;
      do {
        s[startIdx++] = (char) b;
        b = nextChar();
        ++res;
      } while (!isSpaceChar(b));
      return res;
    }

    public int nextNonSpaceChar() {
      int res = nextChar();
      for (; isSpaceChar(res) || res < 0; res = nextChar()) ;
      return res;
    }

    public int nextChar() {
      if (numberOfChars == -1) {
        throw new RuntimeException();
      }
      if (currentPosition >= numberOfChars) {
        currentPosition = 0;
        try {
          numberOfChars = stream.read(buffer);
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
        if (numberOfChars <= 0) {
          return -1;
        }
      }
      return buffer[currentPosition++];
    }

    public boolean isSpaceChar(int c) {
      return c == ' ' || c == '\t' || isEndOfLineChar(c);
    }

    public boolean isEndOfLineChar(int c) {
      return c == '\n' || c == '\r' || c < 0;
    }

  }
}


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

public class CF {
    private FastScanner in;
    private PrintWriter out;

    final int mod = (int) 1e9 + 7;

    private long f(String s, int digit) {
        final int n = s.length();
        int[][] dp = new int[2][n + 1]; // [less][cntBigger] -> sum
        dp[0][0] = 1;
        int[][] ndp = new int[2][n + 1];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < 2; j++) {
                Arrays.fill(ndp[j], 0);
            }
            for (int less = 0; less < 2; less++) {
                for (int cntBigger = 0; cntBigger <= n; cntBigger++) {
                    int cur = dp[less][cntBigger];
                    if (cur == 0) {
                        continue;
                    }
                    int max = less == 1 ? 9 : (s.charAt(i) - '0');
                    for (int next = 0; next <= max; next++) {
                        int nextLess = (less == 1) || (next < max) ? 1 : 0;
                        int nextCntBigger = cntBigger + ((next >= digit) ? 1 : 0);
                        ndp[nextLess][nextCntBigger] += cur;
                        while (ndp[nextLess][nextCntBigger] >= mod) {
                            ndp[nextLess][nextCntBigger] -= mod;
                        }
                    }
                }
            }
            int[][] tmp = dp;
            dp = ndp;
            ndp = tmp;
        }
        long result = 0;
        for (int less = 0; less < 2; less++) {
            long sum = 0;
            for (int cntBigger = 1; cntBigger <= n; cntBigger++) {
                sum = (sum * 10 + 1) % mod;
                result = (result + sum * dp[less][cntBigger]) % mod;
            }
        }
        return result % mod;
    }

    private void solve() {
        final String number = in.next();
        long result = 0;
        for (int digit = 1; digit < 10; digit++) {
            long cur = f(number, digit);
            result += cur;
        }
        out.println(result % mod);
    }

    private void run() {
        try {
            in = new FastScanner(new File("CF.in"));
            out = new PrintWriter(new File("CF.out"));

            solve();

            out.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    private void runIO() {
        in = new FastScanner(System.in);
        out = new PrintWriter(System.out);

        solve();

        out.close();
    }

    private class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        FastScanner(File f) {
            try {
                br = new BufferedReader(new FileReader(f));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

        FastScanner(InputStream f) {
            br = new BufferedReader(new InputStreamReader(f));
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return null;
                st = new StringTokenizer(s);
            }
            return st.nextToken();
        }

        boolean hasMoreTokens() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return false;
                st = new StringTokenizer(s);
            }
            return true;
        }

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

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

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

    public static void main(String[] args) {
        new CF().runIO();
    }
}


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

public class cf908G {
	final static int MOD = 1_000_000_007;

	public static void main(String[] argv) {
		cf908G pro = new cf908G();

		InputStream fin = null;
		if (System.getProperty("ONLINE_JUDGE") == null) {
			try {
				fin = new FileInputStream("input.txt");
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		} else {
			fin = System.in;
		}
		pro.solve(new Scanner(fin), System.out);
	}

	private void solve(Scanner scanner, PrintStream out) {
		long ans = 0;
		String X = scanner.next();
		for (int x = 0; x < 9; x++) {
			ans = (ans + solve2(x, X)) % MOD;
		}
		out.println((ans % MOD + MOD) % MOD);
	}

	private long solve2(int x, String X) {
		int[][][] f = new int[X.length() + 1][X.length() + 1][2];
		f[0][0][1] = 1;

		int n = X.length();
		for (int i = 0; i < n; i++) {
			for (int j = 0; j <= n; j++) {
				for (int u = 0; u < 2; u++) {
					int val = f[i][j][u];
					if (val == 0) continue;

					for (int num = 0; num < 10; num++) {
						int Xi = X.charAt(i) - '0';
						if (u == 1 && num > Xi) break;
						int _i = i + 1;
						int _j = num <= x ? j + 1 : j;
						int _u = u == 1 && num == Xi ? 1 : 0;

						f[_i][_j][_u] = (f[_i][_j][_u] + val) % MOD;
					}
				}
			}
		}

		long base = 1;
		long ret = 0;
		for (int i = n; i > 0; i--) {
			long t = 0;
			for (int j = 0; j < i; j++) {
				t = (t + f[n][j][0] + f[n][j][1]) % MOD;
			}

			ret = (ret + base * t) % MOD;

			base = (base * 10) % MOD;
		}
		return ret;
	}

}


import java.io.*;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.atomic.AtomicIntegerArray;

public class Solution {

    public static void main(String[] args) throws Exception {
        MyReader reader = new MyReader(System.in);
//        MyReader reader = new MyReader(new FileInputStream("input.txt"));
        MyWriter writer = new MyWriter(System.out);
        new Solution().run(reader, writer);
        writer.close();
    }

    private void run(MyReader reader, MyWriter writer) throws Exception {
        char[] c = reader.nextCharArray();
        int n = c.length;
        int[] x = new int[n];
        for (int i = 0; i < n; i++) {
            x[i] = c[i] - '0';
        }
        long mod = 1_000_000_007;
        long[] p = new long[n + 1];
        long[] s = new long[n + 1];
        p[0] = 1;
        for (int i = 1; i <= n; i++) {
            p[i] = p[i - 1] * 10 % mod;
        }
        s[n] = 1;
        for (int i = n - 1; i >= 0; i--) {
            s[i] = (p[n - i - 1] * x[i] + s[i + 1]) % mod;
        }
        long[][][] d = new long[n + 1][n + 1][2];
        long ans = 0;
        for (int i = 1; i < 10; i++) {
            for (long[][] q : d) {
                for (long[] w : q) {
                    Arrays.fill(w, 0);
                }
            }
            for (int j = 0; j <= n; j++) {
                d[j][0][0] = s[j];
                d[j][0][1] = p[n - j];
            }
            for (int j = n - 1; j >= 0; j--) {
                for (int k = 1; k <= n; k++) {
                    for (int l = 1; l >= 0; l--) {
                        int lim = l == 1 ? 10 : x[j] + 1;
                        for (int m = 0; m < lim; m++) {
                            d[j][k][l] += d[j + 1][k - (m >= i ? 1 : 0)][l == 1 || m < x[j] ? 1 : 0];
                            d[j][k][l] %= mod;
                        }
                    }
                    if (j == 0) {
                        ans = (ans + p[k - 1] * d[0][k][0]) % mod;
                    }
                }
            }
        }
        System.out.println(ans);
    }

    static class MyReader {

        final BufferedInputStream in;
        final int bufSize = 1 << 16;
        final byte buf[] = new byte[bufSize];
        int i = bufSize;
        int k = bufSize;
        boolean end = false;
        final StringBuilder str = new StringBuilder();

        MyReader(InputStream in) {
            this.in = new BufferedInputStream(in, bufSize);
        }

        int nextInt() throws IOException {
            return (int) nextLong();
        }

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

        int[][] nextIntMatrix(int n, int m) throws IOException {
            int[][] a = new int[n][0];
            for (int j = 0; j < n; j++) {
                a[j] = nextIntArray(m);
            }
            return a;
        }

        long nextLong() throws IOException {
            int c;
            long x = 0;
            boolean sign = true;
            while ((c = nextChar()) <= 32) ;
            if (c == '-') {
                sign = false;
                c = nextChar();
            }
            if (c == '+') {
                c = nextChar();
            }
            while (c >= '0') {
                x = x * 10 + (c - '0');
                c = nextChar();
            }
            return sign ? x : -x;
        }

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

        int nextChar() throws IOException {
            if (i == k) {
                k = in.read(buf, 0, bufSize);
                i = 0;
            }
            return i >= k ? -1 : buf[i++];
        }

        String nextString() throws IOException {
            if (end) {
                return null;
            }
            str.setLength(0);
            int c;
            while ((c = nextChar()) <= 32 && c != -1) ;
            if (c == -1) {
                end = true;
                return null;
            }
            while (c > 32) {
                str.append((char) c);
                c = nextChar();
            }
            return str.toString();
        }

        String nextLine() throws IOException {
            if (end) {
                return null;
            }
            str.setLength(0);
            int c = nextChar();
            while (c != '\n' && c != '\r' && c != -1) {
                str.append((char) c);
                c = nextChar();
            }
            if (c == -1) {
                end = true;
                if (str.length() == 0) {
                    return null;
                }
            }
            if (c == '\r') {
                nextChar();
            }
            return str.toString();
        }

        char[] nextCharArray() throws IOException {
            return nextString().toCharArray();
        }

        char[][] nextCharMatrix(int n) throws IOException {
            char[][] a = new char[n][0];
            for (int i = 0; i < n; i++) {
                a[i] = nextCharArray();
            }
            return a;
        }
    }

    static class MyWriter {

        final BufferedOutputStream out;
        final int bufSize = 1 << 16;
        final byte buf[] = new byte[bufSize];
        int i = 0;
        final byte c[] = new byte[30];
        static final String newLine = System.getProperty("line.separator");

        MyWriter(OutputStream out) {
            this.out = new BufferedOutputStream(out, bufSize);
        }

        void print(long x) throws IOException {
            int j = 0;
            if (i + 30 >= bufSize) {
                flush();
            }
            if (x < 0) {
                buf[i++] = (byte) ('-');
                x = -x;
            }
            while (j == 0 || x != 0) {
                c[j++] = (byte) (x % 10 + '0');
                x /= 10;
            }
            while (j-- > 0)
                buf[i++] = c[j];
        }

        void print(int[] m) throws IOException {
            for (int a : m) {
                print(a);
                print(' ');
            }
        }

        void print(long[] m) throws IOException {
            for (long a : m) {
                print(a);
                print(' ');
            }
        }

        void print(String s) throws IOException {
            for (int i = 0; i < s.length(); i++) {
                print(s.charAt(i));
            }
        }

        void print(char x) throws IOException {
            if (i == bufSize) {
                flush();
            }
            buf[i++] = (byte) x;
        }

        void print(char[] m) throws IOException {
            for (char c : m) {
                print(c);
            }
        }

        void println(String s) throws IOException {
            print(s);
            println();
        }

        void println() throws IOException {
            print(newLine);
        }

        void flush() throws IOException {
            out.write(buf, 0, i);
            out.flush();
            i = 0;
        }

        void close() throws IOException {
            flush();
            out.close();
        }
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskG solver = new TaskG();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskG {
        static final long MODULO = (long) (1e9 + 7);

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            String x = in.next();
            int[][] comb = new int[x.length() + 2][x.length() + 2];
            comb[0][0] = 1;
            for (int i = 1; i < comb.length; ++i) {
                comb[i][0] = 1;
                for (int j = 1; j < comb.length; ++j) {
                    comb[i][j] = (comb[i - 1][j - 1] + comb[i - 1][j]) % (int) MODULO;
                }
            }
            int[][] pow = new int[11][x.length() + 2];
            for (int i = 0; i < pow.length; ++i) {
                pow[i][0] = 1;
                for (int j = 1; j < pow[i].length; ++j) {
                    pow[i][j] = (int) (i * (long) pow[i][j - 1] % MODULO);
                }
            }
            int[] oneSum = new int[x.length() + 2];
            for (int i = 1; i < oneSum.length; ++i) {
                oneSum[i] = (int) ((10 * (long) oneSum[i - 1] + 1) % MODULO);
            }

            int[][] s1 = new int[10][x.length() + 1];
            int[][] s2 = new int[10][x.length() + 1];
            for (int what = 1; what <= 9; ++what) {
                for (int max = 0; max <= x.length(); ++max) {
                    long sum1 = 0;
                    long sum2 = 0;
                    for (int equalExtra = 0; equalExtra <= max; ++equalExtra) {
                        long cways = 1;
                        cways *= comb[max][equalExtra];
                        cways %= MODULO;
                        cways *= pow[what][max - equalExtra];
                        cways %= MODULO;
                        sum1 += cways * oneSum[equalExtra];
                        sum1 %= MODULO;
                        sum2 += cways;
                        sum2 %= MODULO;
                    }
                    s1[what][max] = (int) sum1;
                    s2[what][max] = (int) sum2;
                }
            }

            int[] sofar = new int[10];
            long res = 0;
            for (int firstLess = 0; firstLess < x.length(); ++firstLess) {
                int min = 0;
                int max = x.charAt(firstLess) - '0';
                if (firstLess < x.length() - 1) --max;
                for (int dig = min; dig <= max; ++dig) {
                    ++sofar[dig];
                    int totalSofar = firstLess + 1;
                    int sofarBigger = 0;
                    for (int what = 9; what >= 1; --what) {
                        int sofarThisOrLess = totalSofar - sofarBigger;
                        int sofarThis = sofar[what];
                        int sofarLess = sofarThisOrLess - sofarThis;
                        for (int bigger = sofarBigger; bigger + sofarThisOrLess <= x.length(); ++bigger) {
                            long ways = comb[x.length() - totalSofar][bigger - sofarBigger];
                            ways *= pow[9 - what][bigger - sofarBigger];
                            ways %= MODULO;
                            long sum1 = s1[what][x.length() - bigger - sofarThisOrLess];
                            long sum2 = s2[what][x.length() - bigger - sofarThisOrLess];
                            long sum = (sum1 * (long) pow[10][sofarThis] + sum2 * oneSum[sofarThis]) % MODULO;
                            sum *= pow[10][bigger];
                            sum %= MODULO;
                            res = (res + sum * ways % MODULO * what) % MODULO;
                        }
                        sofarBigger += sofarThis;
                    }
                    --sofar[dig];
                }
                ++sofar[x.charAt(firstLess) - '0'];
            }
            out.println(res);
        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

    }
}


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

public class MainG {
	static StdIn in = new StdIn();
	static PrintWriter out = new PrintWriter(System.out);
	static long M=(long)1e9+7;

	public static void main(String[] args) {
		char[] cs = in.next().toCharArray();
		int n=cs.length;
		int[] x = new int[n];
		for(int i=0; i<n; ++i)
			x[i]=cs[i]-'0';
		long[] dp1 = new long[n+1];
		for(int i=0; i<n; ++i)
			dp1[i+1]=(x[i]+dp1[i]*10)%M;
		long ans=0;
		for(int d1=1; d1<=9; ++d1) {
			long[][] dp2 = new long[2][n+1];
			for(int i=0; i<n; ++i) {
				dp2[0][i+1]=x[i]>=d1?(10*dp2[0][i]+1)%M:dp2[0][i];
				for(int d2=0; d2<x[i]; ++d2)
					dp2[1][i+1]=((d2>=d1?10*(dp2[0][i]+dp2[1][i])+dp1[i]+1:dp2[0][i]+dp2[1][i])+dp2[1][i+1])%M;
				for(int d2=x[i]; d2<=9; ++d2)
					dp2[1][i+1]=((d2>=d1?10*dp2[1][i]+dp1[i]:dp2[1][i])+dp2[1][i+1])%M;
			}
			ans+=dp2[0][n]+dp2[1][n];
		}
		out.println(ans%M);
		out.close();
	}

	interface Input {
		public String next();
		public String nextLine();
		public int nextInt();
		public long nextLong();
		public double nextDouble();
	}
	static class StdIn implements Input {
		final private int BUFFER_SIZE = 1 << 16;
		private DataInputStream din;
		private byte[] buffer;
		private int bufferPointer, bytesRead;
		public StdIn() {
			din = new DataInputStream(System.in);
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}
		public StdIn(InputStream in) {
			try{
				din = new DataInputStream(in);
			} catch(Exception e) {
				throw new RuntimeException();
			}
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}
		public String next() {
			int c;
			while((c=read())!=-1&&(c==' '||c=='\n'||c=='\r'));
			StringBuilder s = new StringBuilder();
			while (c != -1)
			{
				if (c == ' ' || c == '\n'||c=='\r')
					break;
				s.append((char)c);
				c=read();
			}
			return s.toString();
		}
		public String nextLine() {
			int c;
			while((c=read())!=-1&&(c==' '||c=='\n'||c=='\r'));
			StringBuilder s = new StringBuilder();
			while (c != -1)
			{
				if (c == '\n'||c=='\r')
					break;
				s.append((char)c);
				c = read();
			}
			return s.toString();
		}
		public int nextInt() {
			int ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do
				ret = ret * 10 + c - '0';
			while ((c = read()) >= '0' && c <= '9');

			if (neg)
				return -ret;
			return ret;
		}
		public int[] readIntArray(int n) {
			int[] ar = new int[n];
			for(int i=0; i<n; ++i)
				ar[i]=nextInt();
			return ar;
		}
		public long nextLong() {
			long ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do
				ret = ret * 10 + c - '0';
			while ((c = read()) >= '0' && c <= '9');
			if (neg)
				return -ret;
			return ret;
		}
		public long[] readLongArray(int n) {
			long[] ar = new long[n];
			for(int i=0; i<n; ++i)
				ar[i]=nextLong();
			return ar;
		}
		public double nextDouble() {
			double ret = 0, div = 1;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do
				ret = ret * 10 + c - '0';
			while ((c = read()) >= '0' && c <= '9');
			if (c == '.')
				while ((c = read()) >= '0' && c <= '9')
					ret += (c - '0') / (div *= 10);
			if (neg)
				return -ret;
			return ret;
		}
		private void fillBuffer() throws IOException {
			bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
			if (bytesRead == -1)
				buffer[0] = -1;
		}
		private byte read() {
			try{
				if (bufferPointer == bytesRead)
					fillBuffer();
				return buffer[bufferPointer++];
			} catch(IOException e) {
				throw new RuntimeException();
			}
		}
		public void close() throws IOException {
			if (din == null)
				return;
			din.close();
		}
	}
}


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

public class MainG {
	static StdIn in = new StdIn();
	static PrintWriter out = new PrintWriter(System.out);
	static long M=(long)1e9+7;

	public static void main(String[] args) {
		char[] cs = in.next().toCharArray();
		int n=cs.length;
		int[] x = new int[n];
		for(int i=0; i<n; ++i)
			x[i]=cs[i]-'0';
		long[] dp1 = new long[n+1];
		for(int i=0; i<n; ++i)
			dp1[i+1]=(x[i]+dp1[i]*10)%M;
		//out.println(Arrays.toString(dp1));
		long ans=0;
		for(int d1=1; d1<=9; ++d1) {
			long[][] dp2 = new long[2][n+1];
			for(int i=0; i<n; ++i) {
				dp2[0][i+1]=x[i]>=d1?(10*dp2[0][i]+1)%M:dp2[0][i];
				dp2[1][i+1]=x[i]>=d1?(10*dp2[1][i]+dp1[i])%M:dp2[1][i];
				for(int d2=0; d2<x[i]; ++d2)
					dp2[1][i+1]=((d2>=d1?10*(dp2[0][i]+dp2[1][i])+dp1[i]+1:dp2[0][i]+dp2[1][i])+dp2[1][i+1])%M;
				for(int d2=x[i]+1; d2<=9; ++d2)
					dp2[1][i+1]=((d2>=d1?10*dp2[1][i]+dp1[i]:dp2[1][i])+dp2[1][i+1])%M;
			}
			ans+=dp2[0][n]+dp2[1][n];
			//out.println(dp2[0][n]+" "+dp2[1][n]);
		}
		out.println(ans%M);
		out.close();
	}

	interface Input {
		public String next();
		public String nextLine();
		public int nextInt();
		public long nextLong();
		public double nextDouble();
	}
	static class StdIn implements Input {
		final private int BUFFER_SIZE = 1 << 16;
		private DataInputStream din;
		private byte[] buffer;
		private int bufferPointer, bytesRead;
		public StdIn() {
			din = new DataInputStream(System.in);
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}
		public StdIn(InputStream in) {
			try{
				din = new DataInputStream(in);
			} catch(Exception e) {
				throw new RuntimeException();
			}
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}
		public String next() {
			int c;
			while((c=read())!=-1&&(c==' '||c=='\n'||c=='\r'));
			StringBuilder s = new StringBuilder();
			while (c != -1)
			{
				if (c == ' ' || c == '\n'||c=='\r')
					break;
				s.append((char)c);
				c=read();
			}
			return s.toString();
		}
		public String nextLine() {
			int c;
			while((c=read())!=-1&&(c==' '||c=='\n'||c=='\r'));
			StringBuilder s = new StringBuilder();
			while (c != -1)
			{
				if (c == '\n'||c=='\r')
					break;
				s.append((char)c);
				c = read();
			}
			return s.toString();
		}
		public int nextInt() {
			int ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do
				ret = ret * 10 + c - '0';
			while ((c = read()) >= '0' && c <= '9');

			if (neg)
				return -ret;
			return ret;
		}
		public int[] readIntArray(int n) {
			int[] ar = new int[n];
			for(int i=0; i<n; ++i)
				ar[i]=nextInt();
			return ar;
		}
		public long nextLong() {
			long ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do
				ret = ret * 10 + c - '0';
			while ((c = read()) >= '0' && c <= '9');
			if (neg)
				return -ret;
			return ret;
		}
		public long[] readLongArray(int n) {
			long[] ar = new long[n];
			for(int i=0; i<n; ++i)
				ar[i]=nextLong();
			return ar;
		}
		public double nextDouble() {
			double ret = 0, div = 1;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do
				ret = ret * 10 + c - '0';
			while ((c = read()) >= '0' && c <= '9');
			if (c == '.')
				while ((c = read()) >= '0' && c <= '9')
					ret += (c - '0') / (div *= 10);
			if (neg)
				return -ret;
			return ret;
		}
		private void fillBuffer() throws IOException {
			bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
			if (bytesRead == -1)
				buffer[0] = -1;
		}
		private byte read() {
			try{
				if (bufferPointer == bytesRead)
					fillBuffer();
				return buffer[bufferPointer++];
			} catch(IOException e) {
				throw new RuntimeException();
			}
		}
		public void close() throws IOException {
			if (din == null)
				return;
			din.close();
		}
	}
}


import java.util.Arrays;

public class Main {

	private static void solve() {
		int n = ni();
		String[] lines = new String[n];
		for(int i = 0; i < n; i ++) {
			lines[i] = next();
		}
		int mod = 1000000000 + 7;

		long[][] dp = new long[2][n + 1];
		dp[0][0] = 1;
		for (int i = 0; i < n; i ++) {
			int from = i % 2;
			int to = (i + 1) % 2;
			boolean flg = i == 0 || lines[i - 1].equals("s");
			if (flg) {
				long v = Arrays.stream(dp[from]).sum();
				for (int j = 0; j <= n; j ++) {
					dp[to][j] += v;
					dp[to][j] %= mod;
					v -= dp[from][j];
				}
			} else {
				for (int j = 0; j < n; j ++) {
					dp[to][j + 1] += dp[from][j];
					dp[to][j + 1] %= mod;
				}
			}
			Arrays.fill(dp[from], 0);
		}
		long ret = Arrays.stream(dp[n % 2]).sum() % mod;
		System.out.println(ret);
	}

	public static void main(String[] args) {
		new Thread(null, new Runnable() {
			@Override
			public void run() {
				long start = System.currentTimeMillis();
				String debug = args.length > 0 ? args[0] : null;
				if (debug != null) {
					try {
						is = java.nio.file.Files.newInputStream(java.nio.file.Paths.get(debug));
					} catch (Exception e) {
						throw new RuntimeException(e);
					}
				}
				reader = new java.io.BufferedReader(new java.io.InputStreamReader(is), 32768);
				solve();
				out.flush();
				tr((System.currentTimeMillis() - start) + "ms");
			}
		}, "", 64000000).start();
	}

	private static java.io.InputStream is = System.in;
	private static java.io.PrintWriter out = new java.io.PrintWriter(System.out);
	private static java.util.StringTokenizer tokenizer = null;
	private static java.io.BufferedReader reader;

	public static String next() {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			try {
				tokenizer = new java.util.StringTokenizer(reader.readLine());
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
		return tokenizer.nextToken();
	}

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

	private static long nl() {
		return Long.parseLong(next());
	}

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

	private static char[] ns() {
		return next().toCharArray();
	}

	private static long[] nal(int n) {
		long[] a = new long[n];
		for (int i = 0; i < n; i++)
			a[i] = nl();
		return a;
	}

	private static int[][] ntable(int n, int m) {
		int[][] table = new int[n][m];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				table[i][j] = ni();
			}
		}
		return table;
	}

	private static int[][] nlist(int n, int m) {
		int[][] table = new int[m][n];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				table[j][i] = ni();
			}
		}
		return table;
	}

	private static int ni() {
		return Integer.parseInt(next());
	}

	private static void tr(Object... o) {
		if (is != System.in)
			System.out.println(java.util.Arrays.deepToString(o));
	}
}


import java.util.*;
import java.io.*;
import java.lang.*;
import java.math.*;

public class C {
	static final long MOD = 1_000_000_007;
	public static void main(String[] args) throws Exception {
		FastScanner sc = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		int N = sc.nextInt();
		long[][] dp = new long[N][N];
		dp[0][0] = 1L;
		for(int i = 0; i < N-1; i++) {
			char oper = sc.next().charAt(0);
			if(oper == 'f') {
				dp[i+1][0] = 0L;
				for(int j = 1; j < N; j++) {
					dp[i+1][j] = dp[i][j-1];
				}
			}
			else {
				dp[i+1][N-1] = dp[i][N-1];
				for(int j = N-2; j >= 0; j--) {
					dp[i+1][j] = (dp[i+1][j+1] + dp[i][j]) % MOD;
				}
			}
		}
		long res = 0;
		for(int i = 0; i < N; i++) {
			res += dp[N-1][i];
			res %= MOD;
		}
		out.println(res);
		out.flush();
	}

	static class FastScanner {
		public BufferedReader reader;
		public StringTokenizer tokenizer;

		public FastScanner() {
			reader = new BufferedReader(new InputStreamReader(System.in), 32768);
			tokenizer = null;
		}

		public String next() {
			while (tokenizer == null || !tokenizer.hasMoreTokens()) {
				try {
					tokenizer = new StringTokenizer(reader.readLine());
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			}
			return tokenizer.nextToken();
		}

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

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

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

		public String nextLine() {
			try {
				return reader.readLine();
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}

	}
}


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

public class C {

	public static void main(String[] args){
		FastScanner scan = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		n = scan.nextInt(); mod = (int)1e9+7;
		in = new char[n];
		for(int i = 0; i < n; i++) in[i] = scan.next().charAt(0);
		dp = new Long[n][n];
		out.println(go(0, 0));
		out.close();
	}

	static long go(int at, int i) {
		if(at == n-1) return 1;
		if(dp[at][i] != null) return dp[at][i];
		long res = 0;
		if(in[at] == 's') {
			res += go(at+1, i);
			res %= mod;
			if(i > 0) {
				res += go(at, i-1);
				res %= mod;
			}
		} else {
			res += go(at+1, i+1);
			res %= mod;
		}
		return dp[at][i] = res;
	}

	static Long[][] dp;
	static int n, mod;
	static char[] in;

	static class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		public FastScanner() {
			try	{
				br = new BufferedReader(new InputStreamReader(System.in));
				st = new StringTokenizer(br.readLine());
			} catch (Exception e){e.printStackTrace();}
		}

		public String next() {
			if (st.hasMoreTokens())	return st.nextToken();
			try {st = new StringTokenizer(br.readLine());}
			catch (Exception e) {e.printStackTrace();}
			return st.nextToken();
		}

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

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

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

		public String nextLine() {
			String line = "";
			if(st.hasMoreTokens()) line = st.nextToken();
			else try {return br.readLine();}catch(IOException e){e.printStackTrace();}
			while(st.hasMoreTokens()) line += " "+st.nextToken();
			return line;
		}

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

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

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

		public char[][] nextGrid(int n, int m){
			char[][] grid = new char[n][m];
			for(int i = 0; i < n; i++) grid[i] = next().toCharArray();
			return grid;
		}
	}

}


import java.util.* ;

public class PythonIndentation
{
	public static void main(String args[])
	{
		Scanner in = new Scanner(System.in) ;
		int n = in.nextInt() ;
		boolean[] lst = new boolean[n] ;
		for(int i=0;i<n;i++)
		{
			lst[i] = (in.next().equals("s"))?false:true ;
		}
		System.out.println(dp(lst)) ;
	}
	static void  arrayPrinter(int[][] dp)
	{
		System.out.println(":::") ;
		for(int i=0;i<dp.length;i++)
		{
			for(int j=0;j<dp[0].length;j++)
			{
				System.out.print(dp[i][j]+" ") ;
			}
			System.out.println() ;
		}
	}
	static int dp(boolean[] lst)
	{//false in lst means an "s" (simple statement), and true a "f"(for loop)
		int[][] dp = new int[2][lst.length] ;
		dp[0][0] = 1 ;
		for(int i=1;i<lst.length;i++)
		{
			// arrayPrinter(dp) ;
			for(int j=0;j<lst.length;j++)
			{
				if(lst[i-1])//(i-1)st statement is a for loop
				{
					if(j==0)
						dp[i%2][j] = 0 ;
					else
						dp[i%2][j] = dp[(i-1)%2][j-1] ;
				}

				else//i-1 st statement is a simple statement
				{
					if(j==0)
					{
						int temp = 0 ;
						for(int k=0;k<lst.length;k++)
							temp = (temp+dp[(i-1)%2][k])%1000000007 ;
						dp[i%2][j] = temp ;
					}
					else
						dp[i%2][j] = (dp[i%2][j-1]-dp[(i-1)%2][j-1])%1000000007 ;
				}
			}
		}
		int ans = 0 ;
		for(int i=0;i<lst.length;i++)
		{
			ans = (ans + dp[(lst.length-1)%2][i])%1000000007 ;
		}
		if(ans<0)
			ans = ans + 1000000007 ;
		// arrayPrinter(dp) ;
		return ans ;
	}
}


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

public final class PythonIndentation
{
	public static void main(String[] args)
	{
		new PythonIndentation(System.in, System.out);
	}

	static class Solver implements Runnable
	{
		static final int MOD = (int) 1e9 + 7;
		int n;
		char[] arr;
		long[][] dp;
		BufferedReader in;
		PrintWriter out;

		void solve() throws IOException
		{
			n = Integer.parseInt(in.readLine());
			arr = new char[n];
			dp = new long[n + 1][n + 1];

			for (int i = 0; i < n; i++)
				arr[i] = in.readLine().charAt(0);

			for (int i = 0; i <= n; i++)
				Arrays.fill(dp[i], -1);

			dp[0][0] = 1;

			if (arr[0] == 's')
				out.println(find(1, 0));
			else
				out.println(find(1, 1));

/*			System.out.println("dp :");

			for (int i = 0; i <= n; i++)
			{
				System.out.print("i : " + i + " => ");
				for (int j = 0; j <= n; j++)
					System.out.print(dp[i][j] + " ");
				System.out.println();
			}*/
		}

		long find(int curr, int backIndents)
		{
//			System.out.println("curr : " + curr + ", bI : " + backIndents);
			if (backIndents < 0)
				return 0;

			if (curr == n)
				return dp[curr][backIndents] = 1;

			if (dp[curr][backIndents] != -1)
				return dp[curr][backIndents];

			long ans;

			if (arr[curr] == 's')
			{
				if (arr[curr - 1] == 'f')
					ans = find(curr + 1, backIndents);
				else
					ans = CMath.mod(find(curr + 1, backIndents) + find(curr, backIndents - 1), MOD);
			}
			else
			{
				ans = find(curr + 1, backIndents + 1);

				if (arr[curr - 1] != 'f')
				{
//					System.out.println("calling from curr : " + curr + ", bI : " + backIndents);
					ans = CMath.mod(ans + find(curr, backIndents - 1), MOD);
				}
			}

			return dp[curr][backIndents] = ans;
		}

		public Solver(BufferedReader in, PrintWriter out)
		{
			this.in = in;
			this.out = out;
		}

		@Override public void run()
		{
			try
			{
				solve();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}

	}

	static class CMath
	{
		static long mod(long number, long mod)
		{
			return number - (number / mod) * mod;
		}

	}

	private PythonIndentation(InputStream inputStream, OutputStream outputStream)
	{
		BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
		PrintWriter out = new PrintWriter(outputStream);
		Thread thread = new Thread(null, new Solver(in, out), "PythonIndentation", 1 << 29);

		try
		{
			thread.start();
			thread.join();
		}
		catch (InterruptedException e)
		{
			e.printStackTrace();
		}
		finally
		{
			try
			{
				in.close();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}

			out.flush();
			out.close();
		}
	}

}

/*

6
f
f
s
s
s
s
: 10

*/


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

public class PythonIndentation
{
	public static void main(String args[])
	{
		Scanner in = new Scanner(System.in) ;
		int n = in.nextInt() ;
		boolean[] lst = new boolean[n] ;
		for(int i=0;i<n;i++)
		{
			lst[i] = (in.next().equals("s"))?false:true ;
		}
		System.out.println(dp(lst)) ;
	}
	// static void  arrayPrinter(int[][] dp)
	// {
		// System.out.println(":::") ;
		// for(int i=0;i<dp.length;i++)
		// {
			// for(int j=0;j<dp[0].length;j++)
			// {
				// System.out.print(dp[i][j]+" ") ;
			// }
			// System.out.println() ;
		// }
	// }
	static long dp(boolean[] lst)
	{//false in lst means an "s" (simple statement), and true a "f"(for loop)
		long[][] dp = new long[lst.length][lst.length] ;
		dp[0][0] = 1 ;
		for(int i=1;i<lst.length;i++)
		{
			// int sum_i = 0;
			// for(int j=0;j<lst.length;j++)
				// sum_i = (sum_i+dp[i-1][j])%1000000007 ;

			for(int j=0;j<lst.length;j++)
			{
				if(lst[i-1])//(i-1)st statement is a for loop
				{
					if(j==0)
						dp[i][j] = 0 ;
					else
						dp[i][j] = dp[i-1][j-1] ;
				}

				else//i-1 st statement is a simple statement
				{
					if(j==0)
					{
						for(int k=0;k<lst.length;k++)
							dp[i][j] = (dp[i][j]+dp[i-1][k])%1000000007 ;
					}
					else
						dp[i][j] = (dp[i][j-1]-dp[i-1][j-1])%1000000007 ;
					// if(j==lst.length-1)
						// dp[i][j] = dp[i][j-1] ;
					// else
						// dp[i][j] = (dp[i-1][j]+dp[i][j+1])%1000000007 ;
				}
			}
		}
		// for(int i=0;i<lst.length;i++)
			// System.out.print(dp[lst.length-1][i]+" ") ;
		// System.out.println() ;
		long ans = 0 ;
		for(int i=0;i<lst.length;i++)
		{
			ans = (ans + dp[lst.length-1][i])%1000000007 ;
		}
		if(ans<0)
			ans = ans + 1000000007 ;
		return ans ;
	}
}


import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Scanner;
import java.util.TreeSet;

public class Test {
    int readInt() {
        int ans = 0;
        boolean neg = false;
        try {
            boolean start = false;
            for (int c = 0; (c = System.in.read()) != -1; ) {
                if (c == '-') {
                    start = true;
                    neg = true;
                    continue;
                } else if (c >= '0' && c <= '9') {
                    start = true;
                    ans = ans * 10 + c - '0';
                } else if (start) break;
            }
        } catch (IOException e) {
        }
        return neg ? -ans : ans;
    }

    final int N = 5010;
    final int M = 1_000_000_007;
    long[][] dp = new long[2][N];
    long[] sums = new long[N];
    char[] p = new char[N];
    Scanner sca = new Scanner(System.in);
    void start() {
        int n = Integer.parseInt(sca.nextLine());
        int idx = 0;
        Arrays.fill(dp[idx], 0);
        dp[idx][0] = 1;
        for (int i = 0; i < n; i++) p[i] = sca.nextLine().charAt(0);
        for (int i = 0; i < n;) {
            int nidx = idx ^ 1;
            Arrays.fill(dp[nidx], 0);
            Arrays.fill(sums, 0);
            int j = i;
            while (p[j] != 's') j++;
            int levels = j - i;
            i = j+1;
            for (j = n; j >= 0; j--) {
                sums[j] = sums[j + 1] + dp[idx][j];
                if (sums[j] >= M) sums[j] -= M;
            }
            for (j = 0; j <= n; j++) {
                int ind = j + levels;
                if (ind > n) continue;
                dp[nidx][ind] = sums[j];
            }
            idx = nidx;
        }
        long ans = 0;
        for (int i = 0; i <= n; i++) {
            ans += dp[idx][i];
            if (ans >= M) ans -=M;
        }
        System.out.println(ans);
    }

    public static void main(String[] args) {

        new Test().start();

    }
}