import java.util.*;
import java.io.*;
import java.lang.*;
import java.math.*;
public class A {
    public static void main(String[] args) throws Exception {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        // Scanner scan = new Scanner(System.in);
        // PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        // int n = Integer.parseInt(bf.readLine());
        StringTokenizer st = new StringTokenizer(bf.readLine());
        // int[] a = new int[n]; for(int i=0; i<n; i++) a[i] = Integer.parseInt(st.nextToken());
        int n = Integer.parseInt(st.nextToken());
        int R = Integer.parseInt(st.nextToken());
        int r = Integer.parseInt(st.nextToken());
        double hi = Math.PI/Math.asin(r/(R-r+0.0));
        if(hi - Math.ceil(hi) > -0.0000001) hi = 0.001 + hi;
        double cutoff = Math.round(Math.floor(hi));
        if(2*r > R) cutoff = 1;
        if(r > R) cutoff = 0;
        if(n <= cutoff) System.out.println("YES"); else System.out.println("NO");
        // int n = scan.nextInt();

        // out.close(); System.exit(0);
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 *
 * @author Lenovo
 */
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException {
        // TODO code application logic here
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        int[] input = parseArray(in);
        int n = input[0];
        int m = input[1];
        int[] typestable = parseArray(in);
        int s;

        int[] occ = new int[100];
        //ArrayList<Integer> types=new ArrayList<Integer>();
        //Set<Integer> mySet = Set.of(typestable);
        //Set<Integer> targetSet = new HashSet<Integer>();
        for (int i = 1; i <= 100.; i++) {
            occ[i-1] = occurence(i, typestable);
        }
        int res = 0;
        for (int ans = 1; ans <= m; ans++) {
            s = 0;
            for (int i = 1; i <= 100; i++) {
                s += occ[i-1] / ans;
            }
            if (s >= n) {
                res = ans;
            }
        }
        System.out.println(res);

    }

    static int[] parseArray(BufferedReader gi) throws IOException {
        String[] line = gi.readLine().trim().split(" ");
        int[] rez = new int[line.length];
        for (int k = 0; k < line.length; k++) {
            rez[k] = Integer.parseInt(line[k]);
        }
        return rez;
    }

    static int occurence(int ent, int[] tab) {
        int occ = 0;
        for (int i = 0; i < tab.length; i++) {
            if (tab[i] == ent) {
                occ++;
            }
        }
        return occ;
    }

}


import java.util.*;
public class Problem0171e {
    public static void main(String[] args) {
        System.out.println("INTERCAL");
    }
}


import java.util.Scanner;
import java.util.*;

public class T1 {
	public static void main(String args[]) {
		Scanner abc = new Scanner(System.in);
		ArrayList seq = new ArrayList();
		seq.add(0);
		for (int i = 1; i <= 1000; i++) {

			if (i < 10){
				seq.add(i);
			}
			else if (i >= 10 && i < 100) {
				int j = i/10;
					seq.add(j);
					seq.add(i - (j * 10));

			} else if (i >= 100 && i < 1000) {
				int j = i/100;
					seq.add(j);
					seq.add((i - (j * 100))/10);
					seq.add(i - (j * 100)-(((i - (j * 100))/10)*10));

			}else if (i>=1000){
				seq.add(1);
				seq.add(0);
				seq.add(0);
				seq.add(0);
			}
		}
		int n = abc.nextInt();
		System.out.println(seq.get(n));
	}
}


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

public class CF {

	int MAX = 50;

	long[][] power(long n) {
		if (n == 0) {
			long[][] res = new long[MAX][MAX];
			for (int i = 0; i < MAX; i++)
				for (int j = 0; j < MAX; j++)
					if (i != j)
						res[i][j] = Long.MAX_VALUE / 3;
					else
						res[i][j] = 0;
			return res;
		} else {
			if (n == 1) {
				return resOne;
			} else {
				long[][] r1 = power(n / 2);
				long[][] r2 = mul(r1, r1);
				if (n % 2 == 1) {
					r2 = mul(r2, resOne);
				}
				return r2;
			}
		}
	}

	long[][] mul(long[][] a, long[][] b) {
		long[][] res = new long[MAX][MAX];
		for (int i = 0; i < MAX; i++)
			Arrays.fill(res[i], Long.MAX_VALUE / 3);
		for (int i = 0; i < MAX; i++)
			for (int j = 0; j < MAX; j++)
				for (int k = 0; k < MAX; k++)
					res[i][k] = Math.min(res[i][k], a[i][j] + b[j][k]);
		return res;
	}

	long[][] resOne = new long[MAX][MAX];

	void solve() {
		int n = in.nextInt();
		int m = in.nextInt();
		int[] a = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = in.nextInt();
		}
		int[] b = new int[n];
		for (int i = 0; i < n; i++)
			b[i] = in.nextInt();
		int cntHave = m;
		long[][] dx = new long[MAX][MAX];
		for (int i = 0; i < dx.length; i++)
			Arrays.fill(dx[i], Long.MAX_VALUE / 2);
		for (int st = 0; st < 1 << n; st++) {
			int curB = 0;
			int minB = 0;
			int cost = 0;
			for (int i = 0; i < n; i++)
				if (((1 << i) & st) == 0) {
					curB++;
					cost += a[i];
				} else {
					curB--;
					minB = Math.min(minB, curB);
					cost += b[i];
				}
			dx[25 + minB][25 + curB] = Math.min(dx[25 + minB][25 + curB], cost);
		}
		for (int i = 0; i < MAX; i++)
			Arrays.fill(resOne[i], Long.MAX_VALUE / 3);
		for (int i = 0; i < MAX; i++)
			for (int j = 0; j < MAX; j++) {
				int curB = 25 + (j - i);
				if (curB < 0 || curB >= MAX)
					continue;
				for (int sub = Math.max(0, 25 - i); sub < MAX; sub++)
					resOne[i][j] = Math.min(resOne[i][j], dx[sub][curB]);
			}

		long[][] res = power(cntHave);
		out.println(res[0][0]);
	}

	FastScaner in;
	PrintWriter out;

	void run() {
		in = new FastScaner(System.in);
		out = new PrintWriter(System.out);

		solve();

		out.close();
	}

	void runWithFiles() {
		in = new FastScaner(new File("input.txt"));
		try {
			out = new PrintWriter(new File("output.txt"));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}

		solve();

		out.close();
	}

	public static void main(String[] args) {
		Locale.setDefault(Locale.US);
		new CF().run();
	}

	class FastScaner {
		BufferedReader br;
		StringTokenizer st;

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

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

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

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

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

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


import java.util.Scanner;

public class Codeforce {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
    String c= sc.nextLine();
    String[] k= c.split(" ");
    int l=Integer.parseInt(k[0]);
    int r=Integer.parseInt(k[1]);
    int a=Integer.parseInt(k[2]);
    if(l==r)
    {
        if((a % 2)==1)
        {
            a--;
        }
        System.out.println(l+r+a);
    }
    else
    {
        int m = l>r ? r : l;
        int n = l>r ? l : r;
        if((m+a)<=n)
        {
            System.out.println((m+a)*2);
        }
        else
        {
            int e=(((m+a)-n));
            if((e % 2)==1)
            {
                e--;
            }
            System.out.println((n*2)+e);
        }
    }

    }

}


import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.lang.Math.max;
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 D {

	static int gcd(int a, int b) {
		return b == 0 ? a : gcd(b, a % b);
	}

	static void solve() throws Exception {
		int m = scanInt() + 1, a = scanInt(), b = scanInt();
		int cnt[] = new int[a + b];
		for (int i = 0, j = 0;;) {
			++cnt[j];
			if (i >= b) {
				i -= b;
			} else {
				i += a;
			}
			if (i == 0) {
				break;
			}
			j = max(j, i);
		}
		for (int i = 1; i < a + b; i++) {
			cnt[i] += cnt[i - 1];
		}
		long ans = 0;
		for (int i = 0; i < a + b && i < m; i++) {
			ans += cnt[i];
		}
		if (m > a + b) {
			int g = gcd(a, b);
			int from = (a + b) / g, to = m / g;
			ans += (long) (from + to + 1) * (to - from) / 2 * g;
			ans += (long) (m % g) * (to + 1);
		}
		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.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.*;

import javax.naming.InitialContext;

public class C
{
	public static void main(String [] args) throws IOException
	{
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter writer = new PrintWriter(System.out);

		StringTokenizer tokenizer = new StringTokenizer(reader.readLine());
		int l1 = Integer.parseInt(tokenizer.nextToken()) - 1;
		int r1 = Integer.parseInt(tokenizer.nextToken()) - 1;
		int l2 = Integer.parseInt(tokenizer.nextToken()) - 1;
		int r2 = Integer.parseInt(tokenizer.nextToken()) - 1;

		System.out.println(rec((1<<30)-1, l1, r1, l2, r2));
	}

	private static int rec(int len, int l1, int r1, int l2, int r2)
	{
		if(r1 < l1 || r2 < l2)
			return 0;
		if(len == 1)
			return 1;
		if(l1 >= l2 && r1 <= r2)
			return r1-l1+1;
		if(l2 >= l1 && r2 <= r1)
			return r2-l2+1;

		int mid = len/2;

		if(l1 > l2)
			return rec(len, l2, r2, l1, r1);

		if(r1 < mid && r2 < mid)
			return rec(len/2, l1, r1, l2, r2);
		if(l1 > mid && l2 > mid)
			return rec(len/2, l1-mid-1, r1-mid-1, l2-mid-1, r2-mid-1);

		if(r1 < mid && l2 > mid)
			return rec(len/2, l1, r1, l2-mid-1, r2-mid-1);
		if(r1 < mid && l2 <= mid && r2 >= mid)
			return Math.max(rec(len/2, l1, r1, l2, mid-1), rec(len/2, l1, r1, 0, r2-mid-1));

		if(l2 > mid)
			return Math.max(rec(len/2, l1, mid-1, l2-mid-1, r2-mid-1), rec(len/2, 0, r1-mid-1, l2-mid-1, r2-mid-1));

		return Math.max(r1-l2+1, Math.max(rec(len/2, l1, mid-1, 0, r2-mid-1), rec(len/2, l2, mid-1, 0, r1-mid-1)));
	}
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.util.Collection;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.util.Queue;
import java.util.LinkedList;
import java.io.InputStream;

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

    static class CHexadecimalsNumbers {
        public void solve(int testNumber, InputReader in, OutputWriter out) {
            long n = in.nextLong();
            Queue<Long> q = new LinkedList<>();
            q.offer(1L);
            long ans = 0;
            while (!q.isEmpty()) {
                long p = q.poll();
                ans++;

                p *= 10;
                if (p <= n) {
                    q.offer(p);
                }
                if (p + 1 <= n) {
                    q.offer(p + 1);
                }
            }
            out.println(ans);
        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public long nextLong() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

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

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

        public void println(long i) {
            writer.println(i);
        }

    }
}


import java.util.*;
public class Sol{
    public static void main(String args[]){
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        int a = 0, b = 0,c = 0;
        int i = 2;
        while(i < s.length()) {
        	a = s.charAt(i-2) - 'A';
        	b = s.charAt(i-1) - 'A';
        	c = s.charAt(i) - 'A';
//        	System.out.println(a+" "+b+" = "+c);
        	if(c != (a + b)%26) {
        		System.out.println("NO");
        		return;
        	}
        	i++;
        }
        System.out.println("YES");
        return;
    }
}


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

public class bobsAndStages {

	class Bubble {
		int x, y;
		int id1, id2;

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

		int q() {
			if (x == 0 && y == 0) {
				return 0;
			} else if (x > 0 || (x == 0 && y > 0)) {
				return 1;
			} else {
				return 2;
			}
		}
		@Override
		public String toString() {
			return "Bubble [x=" + x + ", y=" + y + ", id1=" + id1 + ", id2=" + id2 + "]";
		}
	}

	long vectMul(Bubble a, Bubble b) {
		return 1L * a.x * b.y - 1L * a.y * b.x;
	}

	long vectMul(Bubble a, Bubble b, Bubble c) {
		return 1L * (b.x - a.x) * (c.y - a.y) - 1L * (b.y - a.y) * (c.x - a.x);
	}

	void solve() {
		int n = in.nextInt();
		int k = in.nextInt();
		Bubble[] a = new Bubble[n];
		for (int i = 0; i < n; i++) {
			a[i] = new Bubble(in.nextInt(), in.nextInt());
		}
		Arrays.sort(a, (p1, p2) -> {
			if (p1.x != p2.x) {
				return p1.x - p2.x;
			}
			return p1.y - p2.y;
		});

		long result = 0;
		long[][] dp = new long[n][k + 1];
		long[][] cost = new long[n][n];
		long INF = Long.MIN_VALUE / 3;
		Bubble[] buf = new Bubble[n];
		for (int i = 0; i < buf.length; i++) {
			buf[i] = new Bubble(0, 0);
		}
		Bubble[] vecs = new Bubble[n * (n - 1)];
		for (int i = 0, tmp = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (i != j) {
					vecs[tmp] = new Bubble(a[j].x - a[i].x, a[j].y - a[i].y);
					vecs[tmp].id1 = i;
					vecs[tmp].id2 = j;
					tmp++;
				}
			}
		}
		Arrays.sort(vecs, (p1, p2) -> {
			int q1 = p1.q(), q2 = p2.q();
			if (q1 != q2) {
				return q1 - q2;
			}
			return -Long.signum(vectMul(p1, p2));
		});
		for (int start = 0; start < n; start++) {
			for (int i = n - 1; i >= start; i--) {
				a[i].x -= a[start].x;
				a[i].y -= a[start].y;
			}
			for (int i = 0; i < n; i++) {
				Arrays.fill(dp[i], INF);
				Arrays.fill(cost[i], INF);
			}
			dp[start][0] = 0;

			int size = 0;
			for (int i = start + 1; i < n; i++) {
				buf[size].x = a[i].x;
				buf[size].y = a[i].y;
				buf[size].id1 = i;
				size++;
			}
			Arrays.sort(buf, 0, size, (p1, p2) -> {
				long v = vectMul(p1, p2);
				return -Long.signum(v);
			});

			for (int i = 0; i < size; i++) {
				for (int j = i + 1; j < size; j++) {
					int p1 = buf[i].id1, p2 = buf[j].id1;
					boolean ok = true;
					for (int t = i + 1; t < j; t++) {
						if (vectMul(buf[i], buf[j], buf[t]) > 0) {
							ok = false;
							break;
						}
					}
					if (ok) {
						cost[p1][p2] = vectMul(buf[i], buf[j]);
					}
				}
			}
			for (int i = 0; i < size; i++) {
				cost[start][buf[i].id1] = cost[buf[i].id1][start] = 0;
			}

			for (Bubble vec : vecs) {
				int p1 = vec.id1, p2 = vec.id2;
				long cst = cost[p1][p2];
				if (cst != INF) {
					long[] dp1 = dp[p1], dp2 = dp[p2];
					for (int i = 0; i < k; i++) {
						dp2[i + 1] = Math.max(dp2[i + 1], dp1[i] + cst);
					}
				}
			}
			result = Math.max(result, dp[start][k]);
		}

		out.printf("%d.%02d\n", result / 2, 50 * (result % 2));
	}

	FastScanner in;
	PrintWriter out;

	void run() {
		in = new FastScanner();
		out = new PrintWriter(System.out);
		solve();
		out.close();
	}

	class FastScanner {
		BufferedReader br;
		StringTokenizer st;

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

		public FastScanner(String s) {
			try {
				br = new BufferedReader(new FileReader(s));
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

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

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

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

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

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


import java.io.*;
import java.util.*;
public class result
{
    public static void main(String[] args)
    {
        int x,y,z;
        boolean flag = false;
        Scanner sc=new Scanner(System.in);
        x=sc.nextInt();
        y=sc.nextInt();
        z=sc.nextInt();
        if(z==0)
        {
            if(x>y)
            {
                System.out.println("+");
                flag=true;
            }
            else if(x<y)
            {
                System.out.println("-");
                flag=true;
            }
            else if(x==y)
            {
                System.out.println("0");
                flag=true;
            }
        }
        else
        {
            if(x+z>=y&&y+z>=x)
            {
                System.out.println("?");
                flag=true;
            }
            else if(x+z>y)
            {
                System.out.println("+");
                flag=true;
            }
            else if(y+z>x)
            {
                System.out.println("-");
                flag=true;
            }
        }
        if(flag==false)
        {
            System.out.println("?");
        }
    }
}


//package school3;

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.BitSet;
import java.util.HashSet;
import java.util.Scanner;

public class F5 {
	Scanner in;
	PrintWriter out;
//	String INPUT = "100000 4";
//	String INPUT = "0 1";
	String INPUT = "";

	int[] dec(int n, int m)
	{
		if(n <= m){
			return new int[]{n, 0};
		}else if(n <= 2 * m){
			return new int[]{n - m, n - m};
		}else{
			return new int[]{n - 2 * m - 1, m};
		}
	}

	int enc(int x, int y, int m)
	{
		if(y == 0){
			return x;
		}else if(x == y){
			return x + m;
		}else{
			return x + 2 * m + 1;
		}
	}

	void solve()
	{
		int m = ni();
		int n = ni();
		if(m <= 0){
			out.println(1);
			return;
		}
		if(n <= 1){
			out.println(-1);
			return;
		}

//		for(int i = 0;i <= 3 * m;i++){
//			int[] co = dec(i, m);
//			tr(co);
//			if(enc(co[0], co[1], m) != i){
//				tr("out!",i);
//			}
//		}

//		int[] co = {0, 0};
//		{
//			if(co[1] == 0){
//				int inf = co[0] + 1;
//				int sup = Math.min(m, co[0] + n);
//				if(inf <= sup){
//					tr(inf, 0, sup, 0, enc(inf, 0, m), enc(sup, 0, m));
//				}
//			}
//		}
//		{
//			int inf = Math.max(co[0], co[1]);
//			if(co[0] == co[1])inf++;
//			int sup = Math.min(m, (n + co[0] + co[1]) / 2);
//
//			if(inf <= sup){
//				tr(inf, inf, sup, sup, enc(inf, inf, m), enc(sup, sup, m));
//			}
//		}
//		{
//			int inf = co[0];
//			if(co[1] == m)inf++;
//			int sup = Math.min(m - 1, co[0] + n - m + co[1]);
//			if(inf <= sup){
//				tr(inf, m, sup, m, enc(inf, m, m), enc(sup, m, m));
//			}
//		}
//		{
//			if(co[1] == m){
//				int inf = co[0] - 1;
//				int sup = Math.max(0, co[0] - n);
//				if(sup <= inf){
//					tr(sup, m, inf, m, enc(sup, m, m), enc(inf, m, m));
//				}
//			}
//		}
//		{
//			int inf = Math.min(co[0], co[1]);
//			if(co[0] == co[1])inf--;
//			int sup = Math.max(1, (-n + co[0] + co[1] + 1) / 2);
//
////			if(sup == 0)sup++;
//			if(sup <= inf){
//				tr(sup, sup, inf, inf, enc(sup, sup, m), enc(inf, inf, m));
//			}
//		}
//		{
//			int inf = co[0];
//			if(co[1] == 0)inf--;
//			int sup = Math.max(0, co[0] - n + co[1]);
//			if(sup <= inf){
//				tr(sup, 0, inf, 0, enc(sup, 0, m), enc(inf, 0, m));
//			}
//		}

		if(n <= Math.sqrt(Math.sqrt(m))){
			solveH(m, n);
		}else{
			solveB(m, n);
		}
	}

	void solveB(int m, int n){
			// (a, 0), (a, a), (a, m)
			BitSet visitedo = new BitSet();
			BitSet visitedh = new BitSet();
			BitSet q = new BitSet();
			q.set(0);
			boolean iso = true;
			int step = 0;

			while(!q.isEmpty()){
				if(!iso && q.get(2 * m))break;
//				tr(step, q);
				BitSet nq = new BitSet();
				if(iso){
					visitedh.or(q);
				}else{
					visitedo.or(q);
				}
				for(int cur = q.nextSetBit(0);cur != -1;cur = q.nextSetBit(cur+1)){
					int[] co = dec(cur, m);
					if(iso){
						{
							if(co[1] == 0){
								int inf = co[0] + 1;
								int sup = Math.min(m, co[0] + n);
								if(inf <= sup){
									nq.set(enc(inf, 0, m), enc(sup, 0, m) + 1);
								}
							}
						}
						{
							int inf = Math.max(co[0], co[1]);
							if(co[0] == co[1])inf++;
							int sup = Math.min(m, (n + co[0] + co[1]) / 2);

							if(inf <= sup){
								nq.set(enc(inf, inf, m), enc(sup, sup, m) + 1);
							}
						}
						{
							int inf = co[0];
							if(co[1] == m)inf++;
							int sup = Math.min(m - 1, co[0] + n - m + co[1]);
							if(inf <= sup){
								nq.set(enc(inf, m, m), enc(sup, m, m) + 1);
							}
						}
					}else{
						{
							if(co[1] == m){
								int inf = co[0] - 1;
								int sup = Math.max(0, co[0] - n);
								if(sup <= inf){
									nq.set(enc(sup, m, m), enc(inf, m, m) + 1);
								}
							}
						}
						{
							int inf = Math.min(co[0], co[1]);
							if(co[0] == co[1])inf--;
							int sup = Math.max(1, (-n + co[0] + co[1] + 1) / 2);

//							if(sup == 0)sup++;
							if(sup <= inf){
								nq.set(enc(sup, sup, m), enc(inf, inf, m) + 1);
							}
						}
						{
							int inf = co[0];
							if(co[1] == 0)inf--;
							int sup = Math.max(0, co[0] - n + co[1]);
							if(sup <= inf){
								nq.set(enc(sup, 0, m), enc(inf, 0, m) + 1);
							}
						}
					}
				}
				if(iso){
					nq.andNot(visitedo);
				}else{
					nq.andNot(visitedh);
				}
				q = nq;
				step++;
				iso = !iso;
			}
			if(q.isEmpty()){
				out.println(-1);
			}else{
				out.println(step);
			}
	}

	void solveH(int m, int n){

		// (a, 0), (a, a), (a, m)
		HashSet<Integer> visitedo = new HashSet<Integer>();
		HashSet<Integer> visitedh = new HashSet<Integer>();
		HashSet<Integer> q = new HashSet<Integer>();
		q.add(0);
		boolean iso = true;
		int step = 0;

		while(!q.isEmpty()){
			if(!iso && q.contains(2 * m))break;
//			tr(step, q);
			HashSet<Integer> nq = new HashSet<Integer>();
			if(iso){
				visitedh.addAll(q);
			}else{
				visitedo.addAll(q);
			}
			for(int cur : q){
				int[] co = dec(cur, m);
				if(iso){
					{
						if(co[1] == 0){
							int inf = co[0] + 1;
							int sup = Math.min(m, co[0] + n);
							if(inf <= sup){
								for(int i = enc(inf, 0, m);i <= enc(sup, 0, m);i++){
									nq.add(i);
								}
							}
						}
					}
					{
						int inf = Math.max(co[0], co[1]);
						if(co[0] == co[1])inf++;
						int sup = Math.min(m, (n + co[0] + co[1]) / 2);

						if(inf == 0)inf = 1;
						if(inf <= sup){
							for(int i = enc(inf, inf, m);i <= enc(sup, sup, m);i++){
								nq.add(i);
							}
						}
					}
					{
						int inf = co[0];
						if(co[1] == m)inf++;
						int sup = Math.min(m - 1, co[0] + n - m + co[1]);
						if(inf <= sup){
							for(int i = enc(inf, m, m);i <= enc(sup, m, m);i++){
								nq.add(i);
							}
						}
					}
				}else{
					{
						if(co[1] == m){
							int inf = co[0] - 1;
							int sup = Math.max(0, co[0] - n);
							if(sup <= inf){
								for(int i = enc(sup, m, m);i <= enc(inf, m, m);i++){
									nq.add(i);
								}
							}
						}
					}
					{
						int inf = Math.min(co[0], co[1]);
						if(co[0] == co[1])inf--;
						int sup = Math.max(1, (-n + co[0] + co[1] + 1) / 2);

//						if(sup == 0)sup++;
						if(sup <= inf){
							for(int i = enc(sup, sup, m);i <= enc(inf, inf, m);i++){
								nq.add(i);
							}
						}
					}
					{
						int inf = co[0];
						if(co[1] == 0)inf--;
						int sup = Math.max(0, co[0] - n + co[1]);
						if(sup <= inf){
							for(int i = enc(sup, 0, m);i <= enc(inf, 0, m);i++){
								nq.add(i);
							}
						}
					}
				}
			}
			if(iso){
				nq.removeAll(visitedo);
			}else{
				nq.removeAll(visitedh);
			}
			q = nq;
			step++;
			iso = !iso;
		}
		if(q.isEmpty()){
			out.println(-1);
		}else{
			out.println(step);
		}
	}

	void run() throws Exception
	{
		in = INPUT.isEmpty() ? new Scanner(System.in) : new Scanner(INPUT);
		out = new PrintWriter(System.out);

		out.println(INPUT);
		solve();
		out.flush();
	}

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

	int ni() { return Integer.parseInt(in.next()); }
	void tr(Object... o) { if(INPUT.length() != 0)System.out.println(o.length > 1 || o[0].getClass().isArray() ? Arrays.deepToString(o) : o[0]); }
}


import java.awt.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import java.util.List;

 public class CandidateCode {
    public static void main(String args[]) throws IOException {
        Scanner sc = new Scanner(System.in);
        int n=sc.nextInt();
        long sum=0;
        for (int i=2;i<n;i++){
            int x=i*(i+1);
            sum+=x;
        }
        System.out.println(sum);
    }
}


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

public class e {
    public static int M = 10;
    public static void main(String[] args) throws Exception{
        FS sc = new FS(System.in);
        int n = sc.nextInt(), i;
        int[] arr = new int[n];
        for (i = 0; i < n; i++)
            arr[i] = sc.nextInt();
        Arrays.sort(arr);
        for (i = 0; i <= n/2; i++) {
            if (arr[i] != arr[0]) {
                System.out.println("Alice");
                return;
            }
        }
        System.out.println("Bob");
    }
    public static int gcd(int a, int b) {
        return (b == 0) ? a : gcd(b, a % b);
    }
    public static class FS {
        BufferedReader br;
        StringTokenizer st;
        FS(InputStream in) {
            br = new BufferedReader(new InputStreamReader(in));
            st = new StringTokenizer("");
        }
        String next() throws Exception {
            if (st.hasMoreTokens())
                return st.nextToken();
            st = new StringTokenizer(br.readLine());
            return next();
        }
        int nextInt() throws Exception {
            return Integer.parseInt(next());
        }
    }
}


//package codeforces;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

/**
 * Created by nitin.s on 09/10/16.
 */
public class PashaAndHamsters {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt(), a = in.nextInt(), b = in.nextInt();
        int[] res = new int[n + 1];
        Arrays.fill(res, -1);
        for(int i = 0; i < a; ++i) {
            int apple = in.nextInt();
            if(res[apple] != -1) continue;
            res[apple] = 1;
        }
        for(int i = 0; i < b; ++i) {
            int apple = in.nextInt();
            if(res[apple] != -1) continue;
            res[apple] = 2;
        }
        for(int i = 1; i <= n; ++i) {
            System.out.print(res[i] + " ");
        }
    }
}


import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Program {
    public static void main(String[] args) {
        Scanner inp = new Scanner(System.in);
        String str = inp.next();
        System.out.println(process(str));
    }

    public static String process(String str) {
        if (str.length() < 26) {
            return "-1";
        }
        int[] count = new int[26];
        for (int num : count) {
            num = 0;
        }
        int cntQuestions = 0;
        for (int i = 0; i < 25; ++i) {
            if (str.charAt(i) == '?') {
                ++cntQuestions;
            }
            else {
                ++count[str.charAt(i) - 'A'];
            }
        }
        for (int i = 25; i < str.length(); ++i) {
            if (str.charAt(i) == '?') {
                ++cntQuestions;
            }
            else {
                ++count[str.charAt(i) - 'A'];
            }

            int curCnt = 0;
            for (int num : count) {
                if (num != 0) {
                    ++curCnt;
                }
            }
            if (curCnt + cntQuestions == 26) {
                String piece = "";
                int pos = 0;
                for (int k = i - 25; k <= i; ++k) {
                    if (str.charAt(k) == '?') {
                        while (count[pos] != 0) {
                            ++pos;
                        }
                        piece += (char)(pos + 'A');
                        ++pos;
                    }
                    else {
                        piece += str.charAt(k);
                    }
                }

                str = str.substring(0, i - 25) + piece + str.substring(i + 1, str.length());
                return str.replace("?", "A");
            }

            if (str.charAt(i - 25) != '?') {
                --count[str.charAt(i - 25) - 'A'];
            }
            else {
                --cntQuestions;
            }
        }
        return "-1";
    }
}


import java.util.Scanner;

public class main {

    public static void main(String[] args) {
        int first_number;
        int second_number;
        String  first = "";
        String rezult = "";
        String kol_number;
        String[] kol_split_number;
        String need_number;
        String[] need_split_number;

        Scanner in          = new Scanner(System.in);
        //first_number        = in.nextInt();
        //second_number       = in.nextInt();
        first               = in.nextLine();
        kol_number          = in.nextLine();
        kol_split_number    = kol_number.split(" ");
        need_number         = in.nextLine();
        need_split_number   = need_number.split(" ");

        for (String i : kol_split_number) {
            for (String j : need_split_number) {
                if ( i.equals(j) ) {
                    rezult = rezult + " " + i;
                }
            }
        }
        System.out.println(rezult);
    }

}


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.ArrayList;

public class main{

    public static void main(String[] args) throws IOException {
        a w = new a();
        w.f();
    }

}
class a{
    StreamTokenizer in;
    PrintWriter out;
    int n, a, b, k, flag;
    long inf;
    long[][] res;
    long[] sum;
    int[][] find;
    int nextInt() throws IOException{
        in.nextToken();
        return (int) in.nval;
    }
    long dp(int ind){
        return ((sum[find[ind][1]] - sum[find[ind][0]] + inf) % inf - res[(flag + 1) % 2][ind] + inf) % inf;
    }
    void f() throws IOException{
        in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(System.out);
        n = nextInt();
        a = nextInt();
        b = nextInt();
        k = nextInt();
        flag = 0;
        find = new int[n][2];
        for (int i = 0; i < n; i++){
            int l = -1; int r = n + 1;
            for (int j = 0; j < n; j++){
                if ((l == -1) && (Math.abs(i - j) < Math.abs(j - b + 1))){
                    l = j;
                } else if ((l != -1) && (Math.abs(i - j) >= Math.abs(j - b + 1))){
                    r = j;
                    break;
                }
            }
            find[i][0] = Math.max(l, 0); find[i][1] = Math.min(r, n);
        }
        inf = 1000000000 + 7;
        sum = new long[n + 1];
        res = new long[2][n];
        res[1][a - 1] = 1;
        for (int i = 0; i < n; i++){
            if (Math.abs(a - 1 - i) < Math.abs(a - b)){
                res[1][i] = 1;
            }
        }
        res[1][a - 1] = 0;
        sum[1] = res[(flag + 1) % 2][0];
        for (int j = 2; j <= n; j++){
            sum[j] = sum[j - 1] + res[(flag + 1) % 2][j - 1];
        }

        for (int i = 0; i < k - 1; i++){
            for (int j = 0; j < n; j++){
                if (j != b - 1){
                    res[flag % 2][j] = dp(j);
                }
            }
            flag++;
            sum[1] = res[(flag + 1) % 2][0];
            for (int j = 2; j <= n; j++){
                sum[j] = (sum[j - 1] + res[(flag + 1) % 2][j - 1]) % inf;
            }
        }
        out.println(sum[n]);
        out.flush();
        out.close();
    }
}


//package eightvc.f;
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 F {
	InputStream is;
	PrintWriter out;
	String INPUT = "";
	char[] s;
	int pos, len;
	int mod = 1000000007;
	int emod = mod-1;
	long modx = (long)mod*emod;

	long[] tm = new long[64];

	long tes(long nume, long mul)
	{
		long B = mul;
		long s0 = 1;
		long s1 = 0;
		long res1 = 0;
		for(int d = 0;d < 63;d++){
			if(nume<<~d<0){
				res1 = (res1 * B + s1 + s0*((nume&(1L<<d)-1)%mod)) % mod;
			}
//			s1 = (s1 * (B+1) + (s0<<d)) % mod;
			s1 = (s1 * (B+1) + s0*((1L<<d)%mod)) % mod;
			s0 = s0 * (B+1) % mod;
			B = B * B % mod;
		}
		return res1;
	}

	void solve()
	{
		for(int i = 0;i < 63;i++){
			tm[i] = (1L<<i)%mod;
		}

		s = ns().toCharArray();
		pos = 0; len = s.length;
		Modnum res = expr();
		assert pos == len;
		out.println(res.v);
	}

	Modnum expr()
	{
		Modnum t = term();
		while(pos < len && s[pos] == '+'){
			pos++;
			Modnum lt = term();
			t = concat(t, lt);
		}
		return t;
	}

	Modnum term()
	{
		Modnum n = number();
		if(pos < len && s[pos] == '-'){
			pos++;
			Modnum ln = number();
			return range(n, ln);
		}
		if(pos < len && s[pos] == '('){
			pos++;
			Modnum e = expr();
			assert s[pos] == ')';
			pos++;
			return repeat(e, n);
		}
		return n;
	}

	long mul10(long v)
	{
		long v2 = v + v;
		if(v2 >= modx)v2 -= modx;
		v = v2 * 5;
		while(v >= modx)v -= modx;
		return v;
	}

	Modnum number()
	{
		long vx = 0;
		int nlen = 0;
		while(pos < len && s[pos] >= '0' && s[pos] <= '9'){
			vx = mul10(vx) + (s[pos]-'0');
			if(vx >= modx)vx -= modx;
			nlen++;
			pos++;
		}
		assert nlen != 0;
		return new Modnum(vx%mod, nlen, vx);
	}

	Modnum concat(Modnum a, Modnum b)
	{
		return new Modnum(
				(a.v * pow(10, b.len, mod) + b.v)% mod,
				(a.len + b.len) % emod
		);
	}

	Modnum range(Modnum a, Modnum b)
	{
		Modnum ret = new Modnum(0, 0);
		long t = pow(10, a.len, mod);
		long px = powSafe(10, a.len-1, modx);
		for(long i = a.len;i <= b.len;i++){
			long npx = mul10(px);
			long inf = i == a.len ? a.vx : px;
			long sup = i == b.len ? b.vx : npx-1;
			if(sup < 0)sup += modx;

			long num = sup-inf+1;
			if(num < 0)num += modx;
			long base = (inf%mod)*sumGP(t, num, mod)%mod;
			// 0 1 ... sup-inf

			num %= modx;
			long mul = t;
			long B = mul;
			long s0 = 1;
			long s1 = 0;
			long res1 = 0;
			long q = 0;
			for(int d = 0;d < 63;d++){
				if(num<<~d<0){
					res1 = (res1 * B + s1 + s0*q) % mod;
					q += tm[d];
					if(q >= mod)q -= mod;
				}
				s1 = (s1 * (B+1) + s0*tm[d]) % mod;
				s0 = s0 * (B+1) % mod;
				B = B * B % mod;
			}
			t = t * 10 % mod;
			px = npx;

			ret = concat(ret, new Modnum((base+res1)%mod, i*(num%emod)%emod));
		}
		return ret;
	}

	Modnum repeat(Modnum a, Modnum rep)
	{
		return new Modnum(
				sumGP(pow(10, a.len, mod), rep.vx, mod) * a.v % mod,
				a.len*(rep.vx%emod)%emod
				);
	}

	public static class Modnum
	{
		public long v;
		public long vx;
		public long len;
		public Modnum(long v, long len) {
			this.v = v;
			this.len = len;
		}
		public Modnum(long v, long len, long vx) {
			this.v = v;
			this.len = len;
			this.vx = vx;
		}
		@Override
		public String toString() {
			return "Datum [v=" + v + ", len=" + len + "]";
		}
	}

	public static long powSafe(long a, long n, long mod)
	{
//		a %= mod;
		long ret = 1; // 1%mod if mod=1,n=0
		int x = 63-Long.numberOfLeadingZeros(n);
		for(;x >= 0;x--){
			ret = mulEx(ret, ret, mod);
			if(n<<~x<0)ret = mulEx(ret, a, mod);
		}
		return ret;
	}

	public static long mul(long a, long b, long mod)
	{
		if(a >= mod || a < 0)a %= mod;
		if(a < 0)a += mod;
		if(b >= mod || b < 0)b %= mod;
		if(b < 0)b += mod;

		long ret = 0;
		int x = 63-Long.numberOfLeadingZeros(b);
		for(;x >= 0;x--){
			ret += ret;
			if(ret >= mod)ret -= mod;
			if(b<<~x<0){
				ret += a;
				if(ret >= mod)ret -= mod;
			}
		}
		return ret;
	}

	public static long mulEx(long a, long b, long mod)
	{
		if(a >= mod || a < 0)a %= mod;
		if(a < 0)a += mod;
		if(b >= mod || b < 0)b %= mod;
		if(b < 0)b += mod;

		long ret = 0;
		int x = 63-Long.numberOfLeadingZeros(b);
		for(;x >= 0;x--){
			ret += ret;
			if(Long.compareUnsigned(ret, mod) >= 0)ret -= mod;
			if(b<<~x<0){
				ret += a;
				if(Long.compareUnsigned(ret, mod) >= 0)ret -= mod;
			}
		}
		return ret;
	}

	public static long sumGP(long a, long n, long mod)
	{
		long smul = 1; // % mod
		long mul = a % mod;
		long ret = 0;
		for(;n > 0;n >>>= 1){
			if((n&1)==1){
				ret = (ret * mul + smul) % mod;
			}
			smul = smul * (mul + 1) % mod;
			mul = mul * mul % mod;
		}
		return ret;
	}

	public static long pow(long a, long n, long mod) {
		//		a %= mod;
		long ret = 1;
		int x = 63 - Long.numberOfLeadingZeros(n);
		for (; x >= 0; x--) {
			ret = ret * ret % mod;
			if (n << 63 - x < 0)
				ret = ret * a % mod;
		}
		return ret;
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


//package cdr;
import java.util.*;
import java.math.*;
import java.io.*;

public class Luck{
	public static InputReader sc;
    public static PrintWriter out;
    public static final int MOD = (int) (1e9 + 7);
    public static void main(String[] args){
    	sc=new InputReader(System.in);
    	out=new PrintWriter(System.out);
    	int n=sc.nextInt();
    	int min=Integer.MAX_VALUE;
    	int a=0;
    	int b=0;
    	for(int i=1;i<=Math.ceil(((double)n/2));i++){
    		if(n%i==0){
    			int temp=n/i;
    			if(temp>i){
    				if(temp-i<min){
    					min=temp-i;
    					b=temp;
    					a=i;
    				}
    			}
    			else{
    				if(i-temp<min){
    					min=i-temp;
    					b=i;
    					a=temp;
    				}
    			}
    		}
    	}
    	out.println(a+" "+b);
    	out.close();
    }

    static int gcd(int a,int b){
    	if(b==0){
    		return a;
    	}
    	return gcd(b,a%b);
    }
    static int lcm(int a,int b){
    	int g;
    	if(a<b){
    		g=gcd(b,a);
    	}
    	else{
    		g=gcd(a,b);
    	}
    	return (a*b)/g;
    }

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

    static void shuffle(int[] A){
    	for(int i=A.length-1;i>0;i--){
    		int j=(int)(Math.random()*(i+1));
    		int temp=A[j];
    		A[j]=A[i];
    		A[i]=temp;
    	}
    }

	public static class Node implements Comparable<Node>{
	    int next;
	    int dist;

	    public Node (int u, int v) {
	        this.next = u;
	        this.dist = v;
	    }

	    public void print() {
	        out.println(next + " " + dist + " ");
	    }

	    public int compareTo(Node n) {
	        return Integer.compare(-this.next, -n.next);
	    }
	}

	public static BigInteger pow(BigInteger base, BigInteger exp) {
	    if(exp.equals(new BigInteger(String.valueOf(0)))){
	        return new BigInteger(String.valueOf(1));
	    }
	    if(exp.equals(new BigInteger(String.valueOf(1))))
	        return base;
	    BigInteger temp=exp.divide(new BigInteger(String.valueOf(2)));
	    BigInteger val = pow(base, temp);
	    BigInteger result = val.multiply(val);
	    result=result.remainder(new BigInteger(String.valueOf(MOD)));
	    BigInteger AND=exp.and(new BigInteger(String.valueOf(1)));
	    if(AND.equals(new BigInteger(String.valueOf(1)))){
	        result = result.multiply(base);
	        result=result.remainder(new BigInteger(String.valueOf(MOD)));
	    }
	    return result;
	}

	static class InputReader {

	    private InputStream stream;
	    private byte[] buf = new byte[8192];
	    private int curChar, snumChars;
	    private SpaceCharFilter filter;

	    public InputReader(InputStream stream) {
	        this.stream = stream;
	    }

	    public int snext() {
	        if (snumChars == -1)
	            throw new InputMismatchException();
	        if (curChar >= snumChars) {
	            curChar = 0;
	            try {
	                snumChars = stream.read(buf);
	            } catch (IOException e) {
	                throw new InputMismatchException();
	            }
	            if (snumChars <= 0)
	                return -1;
	        }
	        return buf[curChar++];
	    }

	    public int nextInt() {
	        int c = snext();
	        while (isSpaceChar(c))
	            c = snext();
	        int sgn = 1;
	        if (c == '-') {
	            sgn = -1;
	            c = snext();
	        }
	        int res = 0;
	        do {
	            if (c < '0' || c > '9')
	                throw new InputMismatchException();
	            res *= 10;
	            res += c - '0';
	            c = snext();
	        } while (!isSpaceChar(c));
	        return res * sgn;
	    }

	    public long nextLong() {
	        int c = snext();
	        while (isSpaceChar(c))
	            c = snext();
	        int sgn = 1;
	        if (c == '-') {
	            sgn = -1;
	            c = snext();
	        }
	        long res = 0;
	        do {
	            if (c < '0' || c > '9')
	                throw new InputMismatchException();
	            res *= 10;
	            res += c - '0';
	            c = snext();
	        } while (!isSpaceChar(c));
	        return res * sgn;
	    }

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

	    public String readString() {
	        int c = snext();
	        while (isSpaceChar(c))
	            c = snext();
	        StringBuilder res = new StringBuilder();
	        do {
	            res.appendCodePoint(c);
	            c = snext();
	        } while (!isSpaceChar(c));
	        return res.toString();
	    }

	    public boolean isSpaceChar(int c) {
	        if (filter != null)
	            return filter.isSpaceChar(c);
	        return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	    }

	    public interface SpaceCharFilter {
	        public boolean isSpaceChar(int ch);
	    }
	}

}


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

public class Main  {

    public BufferedReader in;
    public PrintStream out;

    public boolean log_enabled = false;

    public boolean multiply_tests = false;

    private class TestCase {

        public long modInv(long a, long n) {
	 long i = n, v = 0, d = 1;
	 while (a>0) {
	  long t = i/a, x = a;
	  a = i % x;
	  i = x;
	  x = d;
	  d = v - t*x;
	  v = x;
	 }
	 v %= n;
	 if (v<0) v = (v+n)%n;
	 return v;
	}

        public Object solve() {

            long M = 1000000007;
            int n = readInt();
            long x = 1;

            long r;
            for (r=2; r<=n; r++)
            {
                x = (x*r)%M;
            }

            int i;

            long S = 0;

            long c = 1;
            for (i=0; i<n; i++)
            {
                if (i==0)
                {
                    c = 1;
                }
                else
                {
                    c = (c * (n-1-(i-1))) % M;
                    c = c * modInv(i, M) % M;
                }

                S = (S+c) % M;
            }

            return (x+M-S) % M;

            //return strf("%f", 0);

            //out.printf("Case #%d: \n", caseNumber);
            //return null;
        }

        public int caseNumber;

        TestCase(int number) {
            caseNumber = number;
        }

        public void run(){
            Object r = this.solve();

            if ((r != null))
            {
                //outputCaseNumber(r);
                out.println(r);
            }
        }

        public String impossible(){
            return "IMPOSSIBLE";
        }

        public String strf(String format, Object... args)
        {
            return String.format(format, args);
        }

//        public void outputCaseNumber(Object r){
//            //out.printf("Case #%d:", caseNumber);
//            if (r != null)
//            {
//              //  out.print(" ");
//                out.print(r);
//            }
//            out.print("\n");
//        }
    }

    public void run() {
        //while (true)
        {
            int t = multiply_tests ?  readInt() : 1;
            for (int i = 0; i < t; i++) {
                TestCase T = new TestCase(i + 1);
                T.run();
            }
        }
    }

    public Main(BufferedReader _in, PrintStream _out){
        in = _in;
        out = _out;
    }

    public static void main(String args[]) {
        Locale.setDefault(Locale.US);
        Main S;
        try {
            S = new Main(
                        new BufferedReader(new InputStreamReader(System.in)),
                        System.out
                );
        } catch (Exception e) {
            return;
        }

        S.run();

    }

    private StringTokenizer tokenizer = null;

    public int readInt() {
        return Integer.parseInt(readToken());
    }

    public long readLong() {
        return Long.parseLong(readToken());
    }

    public double readDouble() {
        return Double.parseDouble(readToken());
    }

    public String readLn() {
        try {
            String s;
            while ((s = in.readLine()).length() == 0);
            return s;
        } catch (Exception e) {
            return "";
        }
    }

    public String readToken() {
        try {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                tokenizer = new StringTokenizer(in.readLine());
            }
            return tokenizer.nextToken();
        } catch (Exception e) {
            return "";
        }
    }

    public int[] readIntArray(int n) {
        int[] x = new int[n];
        readIntArray(x, n);
        return x;
    }

    public void readIntArray(int[] x, int n) {
        for (int i = 0; i < n; i++) {
            x[i] = readInt();
        }
    }

    public long[] readLongArray(int n) {
        long[] x = new long[n];
        readLongArray(x, n);
        return x;
    }

    public void readLongArray(long[] x, int n) {
        for (int i = 0; i < n; i++) {
            x[i] = readLong();
        }
    }

    public void logWrite(String format, Object... args) {
        if (!log_enabled) {
            return;
        }

        out.printf(format, args);
    }
}


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

public class YetAnotherNumGame {
	static BufferedReader in;
	static StringTokenizer st;

	static String nextToken() throws IOException {
		if (st==null || !st.hasMoreElements())
			st = new StringTokenizer(in.readLine());
		return st.nextToken();
	}

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

	public static void main(String[] args) throws IOException {
		in = new BufferedReader(new InputStreamReader(System.in));

		int n = nextInt();
		if (n==1) {
			System.out.println(nextInt()==0?"BitAryo":"BitLGM");
		} else if (n==3) {
			int ans = 0;
			for (int i=0; i<3; i++)
				ans ^= nextInt();
			System.out.println(ans==0?"BitAryo":"BitLGM");
		} else {
			int[] max = new int[2];
			for (int i=0; i<n; i++)
				max[i] = nextInt();

			boolean[][] dp = new boolean[max[0]+1][max[1]+1];
			//true if going first wins
			for (int i=0; i<=max[0]; i++) {
				for (int j=0; j<=max[1]; j++) {
					if (i==0 && j==0) continue;
					for (int m=1; m<=i && !dp[i][j]; m++)
						if (!dp[i-m][j]) dp[i][j] = true;
					for (int m=1; m<=j && !dp[i][j]; m++)
						if (!dp[i][j-m]) dp[i][j] = true;
					for (int m=1; m<=j && m<=i && !dp[i][j]; m++)
						if (!dp[i-m][j-m]) dp[i][j] = true;
				}
			}
			System.out.println(dp[max[0]][max[1]]?"BitLGM":"BitAryo");
		}
	}
}


import java.util.*;
public class CF784F {
   public static void main(String[] args){
      Scanner sc = new Scanner(System.in);
      long time = System.currentTimeMillis();
      StringTokenizer s = new StringTokenizer(sc.nextLine());
      int n = Integer.parseInt(s.nextToken());
      long[] a = new long[n];
      for(int i = 0; i < n; i++){
         a[i] = Long.parseLong(s.nextToken());
      }
      Arrays.sort(a);
      while(System.currentTimeMillis() - time < 1000){}
      for(long i : a){
         System.out.print(i + " ");
      }
   }
}


import java.util.Scanner;

public class CF_171A {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int i = in.nextInt();
		int j = Integer.parseInt(new StringBuffer(in.next()).reverse().toString());

		System.out.println(i + j);

	}

}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.io.BufferedReader;
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);
        HZSShufflesCards solver = new HZSShufflesCards();
        solver.solve(1, in, out);
        out.close();
    }

    static class HZSShufflesCards {
        NumberTheory.Mod998 mod = new NumberTheory.Mod998();
        int n;
        int m;

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

            mod.fInv(n + m);

            long phaseSize = 1;
            long p = 1;
            for (int i = 0; p != 0; i++) {
                p = mod.mult(mod.mult(p, n - i), mod.smallInv(n + m - i));
                phaseSize = mod.add(phaseSize, p);
            }

            long answer = 0;
            for (int k = 1; k <= n; k++) {
                long numPhases = mod.mult(m + k, mod.smallInv(k));
                long term = mod.mult(mod.ncr(n, k), mod.mult(numPhases, phaseSize));
                if ((k & 1) == 1)
                    answer = mod.add(answer, term);
                else
                    answer = mod.subtract(answer, term);
            }

            out.println(answer);
        }

    }

    static class InputReader {
        public final 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());
        }

    }

    static class Util {
        public static void ASSERT(boolean assertion) {
            if (!assertion)
                throw new AssertionError();
        }

        private Util() {
        }

    }

    static class IntStack {
        int[] array;
        int size = 0;

        public IntStack() {
            this(8);
        }

        public IntStack(int capacity) {
            array = new int[capacity];
        }

        public void push(int item) {
            if (size >= array.length)
                array = resize(array);
            array[size++] = item;
        }

        public int size() {
            return size;
        }

        public int get(int i) {
            Util.ASSERT(i < size);
            return array[i];
        }

        private static int[] resize(int[] array) {
            int[] newArray = new int[array.length << 1];
            System.arraycopy(array, 0, newArray, 0, array.length);
            return newArray;
        }

        public String toString() {
            int[] trimmed = new int[size];
            System.arraycopy(array, 0, trimmed, 0, size);
            return Arrays.toString(trimmed);
        }

    }

    static class NumberTheory {
        private static void ASSERT(boolean assertion) {
            if (!assertion)
                throw new AssertionError();
        }

        public abstract static class Modulus<M extends NumberTheory.Modulus<M>> {
            final IntStack factorial = new IntStack();
            final IntStack invFactorial = new IntStack();

            public abstract long modulus();

            public Modulus() {
                super();
                factorial.push(1);
                invFactorial.push(1);
            }

            public long fact(int n) {
                while (factorial.size() <= n) {
                    factorial.push((int) mult(factorial.get(factorial.size() - 1), factorial.size()));
                }

                return factorial.get(n);
            }

            public long fInv(int n) {
                int lastKnown = invFactorial.size() - 1;

                if (lastKnown < n) {
                    long[] fInv = new long[n - lastKnown];
                    fInv[0] = inv(fact(n));
                    for (int i = 1; i < fInv.length; i++) {
                        fInv[i] = mult(fInv[i - 1], n - i + 1);
                    }
                    for (int i = fInv.length - 1; i >= 0; i--) {
                        invFactorial.push((int) fInv[i]);
                    }
                }

                return invFactorial.get(n);
            }

            public long ncr(int n, int r) {
                ASSERT(n >= 0);
                if (r < 0 || n < r)
                    return 0;
                return mult(fact(n), mult(fInv(r), fInv(n - r)));
            }

            public long smallInv(int n) {
                return mult(fInv(n), fact(n - 1));
            }

            public long normalize(long x) {
                x %= modulus();
                if (x < 0)
                    x += modulus();
                return x;
            }

            public long add(long a, long b) {
                long v = a + b;
                return v < modulus() ? v : v - modulus();
            }

            public long subtract(long a, long b) {
                long v = a - b;
                return v < 0 ? v + modulus() : v;
            }

            public long mult(long a, long b) {
                return (a * b) % modulus();
            }

            public long inv(long value) {
                long g = modulus(), x = 0, y = 1;
                for (long r = value; r != 0; ) {
                    long q = g / r;
                    g %= r;

                    long temp = g;
                    g = r;
                    r = temp;

                    x -= q * y;

                    temp = x;
                    x = y;
                    y = temp;
                }

                ASSERT(g == 1);
                ASSERT(y == modulus() || y == -modulus());

                return normalize(x);
            }

        }

        public static class Mod998 extends NumberTheory.Modulus<NumberTheory.Mod998> {
            public long modulus() {
                return 998_244_353L;
            }

        }

    }
}


import java.util.Scanner;

public class C {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner s = new Scanner(System.in);
		long n = s.nextLong();
//		System.out.println(Long.MAX_VALUE);
		long prev = 1;
		long cur = 1;
		long wins = 0;
		while (cur <= n) {
			long temp = cur;
			cur = prev+cur;
			prev = temp;
			wins++;
		}
		System.out.println(wins-1);

	}

}


import java.util.*;
import java.io.*;
public class vvvv
{
    static final FS s = new FS();
    static class FS {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer("");
		String next() {
			while(!st.hasMoreElements()) {
				try {
					st = new StringTokenizer(br.readLine());
				} catch(Exception e) {}
			}
			return st.nextToken();
		}
		int nextInt() {
			return Integer.parseInt(next());
		}
		long nextLong() {
			return Long.parseLong(next());
		}
		double nextdouble() {
			return Double.parseDouble(next());
		}
	}
	public static void main(String args[])
	{
	    int t=s.nextInt();
	    outer:for(int i=0;i<t;i++)
	    {
	        int n=s.nextInt();
	            for(int j=2;j<=Math.sqrt(n);j++)
	            {
	                if((n%j)==0)
	                {
	                    System.out.println((n/j)+" "+(n-(n/j)));
	                    continue outer;
	                }
	            }
	            System.out.println("1 "+(n-1));
	           }
	       }
	       }


import java.util.Scanner;

public class CorrectWord {

    public static void main(String[] args)
 {
 		Scanner in=new Scanner(System.in);
		int n=in.nextInt();
		String s=in.next();
		System.out.println(s.replaceAll("([aeiouy])([aeiouy])+","$1"));
	}
}


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

public class Main {
    static class InputReader {
        BufferedReader reader;
        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());
        }

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

    static class OutputWriter {
        PrintWriter writer;

        public OutputWriter(OutputStream stream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(stream)));
        }

        public <T> void print(T x) {
            writer.print(x);
        }

        public <T> void println(T x) {
            writer.println(x);
        }

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

    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        Task t = new Task();
        t.solve(in, out);
        out.close();
    }

    static class Task {
        private long cnk2(int n) {
            return ((long)n * (n - 1)) / 2;
        }

        private long cnk3(int n) {
            return ((long)n * (n - 1) / 2 * (n - 2) / 3);
        }

        private long foo(int A, int B, int C, int L) {
            if (A > C || B > C) return 0;
            int upperBound = Math.min(L, C - A - B);
            if (upperBound < 0) return 0;
            return cnk2(upperBound + 2);
        }

        public void solve(InputReader in, OutputWriter out) {
            int A, B, C, L;
            A = in.nextInt();
            B = in.nextInt();
            C = in.nextInt();
            L = in.nextInt();

            long result = 0;

            for (int x = 0; x <= L; x++) {
                result += foo(A, B, C + x, L - x);
                result += foo(A, C, B + x, L - x);
                result += foo(B, C, A + x, L - x);
            }

            out.println(cnk3(L + 3) - result);
        }
    }
}


import static java.lang.System.out;

import java.util.Scanner;
public class LLPS {

	public static void main(String[] args) {

		Scanner scanner = new Scanner(System.in);
		if (scanner.hasNextLine()){
			String line = scanner.nextLine();
			if (line.length()== 0 || line.length() > 10)
				throw new IllegalArgumentException("Invalid length : " + line.length());
			out.println(largestPa(line));

		}
	}

	public static String largestPa(String str){
		if (str == null || str.length() == 0) return "";
		int[] cache = new int[26];
		for(int i=0; i<str.length(); i++){
			char c = str.charAt(i);
			if (c <'a' || c >'z')
				throw new IllegalArgumentException("Invalid char found in input : " + c);
			cache[c - 'a']++;
		}
		for (int i = cache.length-1; i>=0; i--){
			if (cache[i] >0){
				char[] ch = new char[cache[i]];
				for(int j=0; j<ch.length; j++)
					ch[j] = (char)(((int)'a') + i);
				return new String(ch);
			}
		}
		return "";
	}
}


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.StringTokenizer;
import java.util.TreeSet;

public class E4 {
	static PrintWriter out = new PrintWriter(System.out);
	static int M;
	static int maxN = 200001;
	static int curN;
	static Edge adj[][];
	static int curE[];
	static ArrayList<VecL[]> candidates;
	static int[] sz;
	static final boolean debug = false;
	public static void main(String[] args) {
		FS in = new FS();
		int N = in.nextInt();
		M = in.nextInt();

		ArrayDeque<Edge> es[] = new ArrayDeque[N];
		for(int i = 0; i < N; i++) es[i] = new ArrayDeque<Edge>();
		for(int i = 0; i < N-1; i++) {
			int u = in.nextInt()-1;
			int v = in.nextInt()-1;
			long m = in.nextLong();
			long b = in.nextLong();
			Edge e = new Edge(u,v,m,b);
			es[u].add(e);
			es[v].add(e);
		}

		curN = N;
		adj = new Edge[maxN][3];
		curE = new int[maxN];
		fixTree(0, -1, es);

		if(debug) {
			System.out.println("N= "+ curN);
			for(int i = 0; i < curN; i++) {
				System.out.println(i+" "+adj[i].toString());
			}
		}

		candidates = new ArrayList<>();
		sz = new int[curN];
		solve(0);

		CHT cht = new CHT(1);
		for(VecL[] cs : candidates) {
			for(VecL v : cs) {
				cht.add(v.x, v.y);
			}
		}

		for(int i = 0; i < M; i++) out.print(cht.query(i)+" ");
		out.println();
		out.close();
	}

	static void solve(int node) {
		szdfs(node, -1);
		if(sz[node] == 1) return; // base case, no edges
		Edge e = getEdgetroid(node, -1, sz[node], null);
		e.blocked = true;

		//solve on this guy
		ArrayList<VecL> left = new ArrayList<VecL>();
		ArrayList<VecL> right = new ArrayList<VecL>();
		makeLines(e.u, -1, e.m, e.b, left);
		makeLines(e.v, -1, 0, 0, right);

		VecL[] minskowski = minkowskiSum(getHull(removeDupes(left)), getHull(removeDupes(right)));
		candidates.add(minskowski);

		if(debug) {
			System.out.println("Decomp on: "+e);
			System.out.println("  Left: "+left.toString());
			System.out.println("  Right: "+right.toString());
			System.out.println("  Minskowski: "+Arrays.toString(minskowski));
		}

		//now solve on the remaining stuff
		solve(e.u);
		solve(e.v);
	}

	static void makeLines(int node, int p, long curM, long curB, ArrayList<VecL> vecs) {
		int to = 0;
		for(Edge e : adj[node]) {
			if(e == null || e.blocked || e.to(node) == p) continue;
			to++;
			makeLines(e.to(node), node, curM + e.m, curB + e.b, vecs);
		}
		if(to == 0) vecs.add(new VecL(curM, curB));
	}

	static Edge getEdgetroid(int node, int p, int totalSz, Edge curBest) {
		Edge myBest = null;
		for(Edge e : adj[node]) {
			if(e == null || e.blocked || e.to(node) == p) continue;
			if(myBest == null || myBest.getDif(totalSz) > e.getDif(totalSz)) {
				myBest = e;
			}
		}
		if(curBest != null && (myBest == null || curBest.getDif(totalSz) <= myBest.getDif(totalSz))) return curBest;
		return getEdgetroid(myBest.to(node), node, totalSz, myBest);
	}
	static void szdfs(int node, int p) {
		sz[node] = 1;
		for(Edge e : adj[node]) {
			if(e == null || e.blocked || e.to(node) == p) continue;
			szdfs(e.to(node), node);
			sz[node] += sz[e.to(node)];
		}
	}

	static void fixTree(int node, int p, ArrayDeque<Edge> es[]) {
		int cur = node;
		while(!es[node].isEmpty()) {
			if(es[node].size() <= 2) {
				while(!es[node].isEmpty()) {
					Edge e = es[node].poll();
					e.swap(node, cur);
					int to = e.to(cur);
					addEdge(cur, to, e, false, es);
					fixTree(to, cur, es);
				}
			}
			else {
				//add left edge to my current guy
				Edge e = es[node].poll();
				e.swap(node, cur);
				int to = e.to(cur);
				addEdge(cur, to, e, false, es);
				fixTree(to, cur, es);

				int next = curN++;
				Edge filler = new Edge(cur, next, 0, 0);
				addEdge(cur, next, filler, true, es);
				cur = next;
			}
		}
	}
	static void addEdge(int a, int b, Edge e, boolean filler, ArrayDeque<Edge> es[]) {
		adj[a][curE[a]++] = e;
		adj[b][curE[b]++] = e;
		if(!filler) es[b].remove(e);
	}

	static class Edge{
		int u,v;
		long m,b;
		boolean blocked;
		public Edge(int uu, int vv, long mm, long bb) {
			u=uu; v=vv; m=mm; b=bb;
			blocked = false;
		}
		int to(int node) { return u^v^node; }
		void swap(int from, int to) {
			if(u == from) u = to;
			else if(v == from) v = to;
			else throw null;
		}
		int getDif(int totalSz) {
			int s1 = Math.min(sz[u], sz[v]);
			int s2 = totalSz - Math.min(sz[u], sz[v]);
			return Math.abs(s1-s2);
		}
		@Override
		public String toString() {
			return "[u="+u+" v="+v+" m="+m+" b="+b+"]";
		}
	}

	// Computes the convex hull of the Minkowski sum of 2 convex polygons.
	// Polygons must be in CCW order and returns the sum in same order
	// O(N + M) where N and M are the sizes of the two polygons
	public static VecL[] minkowskiSum(VecL[] c1, VecL[] c2) {
		int n = c1.length, m = c2.length;
		if(n == 1) return simple(c1, c2);
		if(m == 1) return simple(c2, c1);
		VecL[] hull = new VecL[n+m];
		SegL[] s1 = toSeg(c1);
		SegL[] s2 = toSeg(c2);
		int nst = getSt(s1), mst = getSt(s2);
		int rId = 0, ni = nst, mi = mst;
		hull[rId++] = s1[ni].from.add(s2[mi].from);
		while(rId < n+m) {
			if(better(ni,mi,s1,s2)) {
				hull[rId] = hull[rId++-1].add(s1[ni++].dir);
				if(ni >= n) ni = 0;
				if(ni == nst) ni = -1;
			}
			else {
				hull[rId] = hull[rId++-1].add(s2[mi++].dir);
				if(mi >= m) mi = 0;
				if(mi == mst) mi = -1;
			}
//			rId++;
		}
		VecL[] res = new VecL[n+m];
		int cId = 0;
		for(int i = 0; i < hull.length; i++) {
			if(valid(hull[(i-1+hull.length)%hull.length], hull[i], hull[(i+1)%hull.length])) res[cId++] = hull[i];
		}

		return Arrays.copyOf(res, cId);
	}

	static boolean valid(VecL a, VecL b, VecL c) {
		VecL d1 = b.sub(a), d2 = c.sub(b);
		long cross = d1.cross(d2), dot = d1.dot(d2);
		return cross != 0 || (cross == 0 && dot < 0);
	}

	static VecL[] simple(VecL[] pnt, VecL[] c) {
		VecL[] res = new VecL[c.length];
		for(int i = 0; i < c.length; i++) res[i] = c[i].add(pnt[0]);
		return res;
	}

	static SegL[] toSeg(VecL pnts[]) {
		SegL[] res = new SegL[pnts.length];
		for(int i = 0; i < pnts.length; i++) {
			res[i] = new SegL(pnts[i], pnts[(i+1)%pnts.length]);
		}
		return res;
	}

	static boolean better(int i1, int i2, SegL c1[], SegL c2[]) {
		if(i1 == -1) return false;
		if(i2 == -1) return true;
		return c1[i1].dir.radialCompare(c2[i2].dir) <= 0;
	}

	static int getSt(SegL[] segs) {
		if(segs.length == 1) return -1;
		if(segs.length == 2) {
			if(segs[0].dir.y > 0 || (segs[0].dir.y == 0 && segs[0].dir.x > 0)) return 0;
			return 1;
		}
		for(int i = 0; i < segs.length; i++) {
			SegL prev = i == 0 ? segs[segs.length-1] : segs[i-1];
			SegL cur = segs[i];
			if(cur.dir.y >= 0 && prev.dir.y < 0) return i;
		}
		return -1;
	}

	public static VecL[] removeDupes(ArrayList<VecL> points) {
		HashSet<VecL> set=new HashSet<>();
		for (VecL v:points)
			set.add(v);
		int counter=0;
		VecL res[] = new VecL[set.size()];
		for (VecL v:set) res[counter++]=v;
		return res;
	}
	// returns the hull in CCW order
	public static VecL[] getHull(VecL[] points) {
		points=points.clone();
		Arrays.sort(points);
		if (points.length<3)
			return points;
		int n=points.length, j=2, k=2;
		VecL[] lo=new VecL[n], up=new VecL[n];
		lo[0]=points[0];
		lo[1]=points[1];
		for (int i=2; i<n; i++) {
			VecL p=points[i];
			while (j>1&&!right(lo[j-2], lo[j-1], p)) j--;
			lo[j++]=p;
		}
		up[0]=points[n-1];
		up[1]=points[n-2];
		for (int i=n-3; i>=0; i--) {
			VecL p=points[i];
			while (k>1&&!right(up[k-2], up[k-1], p)) k--;
			up[k++]=p;
		}

		VecL[] res=new VecL[j+k-2];
		for (int i=0; i<k; i++) res[i]=up[i];
		for (int i=1; i<j-1; i++) res[k+i-1]=lo[i];
		return res;
	}

	// check if a->b->c are in the right order
	static boolean right(VecL a, VecL b, VecL c) {
		return b.sub(a).cross(c.sub(a))>0;
	}

	static class VecL implements Comparable<VecL>{
		long x,y;
		public VecL(long xx, long yy) {
			x=xx;
			y=yy;
		}
		public VecL add(VecL o) { return new VecL(x+o.x, y+o.y);}
		public VecL sub(VecL o) { return new VecL(x-o.x, y-o.y);}
		public long cross(VecL o) { return x*o.y - y*o.x;}
		public long dot(VecL o) { return x*o.x + y*o.y;}
		public int quadrant() {
			if (x==0||y==0)
				if (y==0)
					if (x>=0)
						return 1;
					else
						return 3;
				else
					if (y>=0)
						return 2;
					else
						return 4;
			if (x>0)
				if (y>0)
					return 1;
				else
					return 4;
			else
				if (y>0)
					return 2;
				else
					return 3;
		}

		public int radialCompare(VecL o) {
			if (quadrant()==o.quadrant())
				return -Long.signum(cross(o));
			return Integer.compare(quadrant(), o.quadrant());
		}
		@Override
		public int compareTo(VecL o) {
			if(x!=o.x) return Long.compare(x, o.x);
			return Long.compare(y, o.y);
		}
		@Override
		public String toString() {
			return "("+x+","+y+")";
		}
		public int hashCode() {
			return Long.hashCode(x<<13^(y*57));
		}

		public boolean equals(Object oo) {
			VecL o=(VecL)oo;
			return x==o.x&&y==o.y;
		}
	}

	static class SegL{
		VecL from, to, dir;
		public SegL(VecL a, VecL b) {
			from=a;
			to=b;
			dir = to.sub(from);
		}
		@Override
		public String toString() {
			return "["+from+" -> "+to+"]";
		}
	}

	static class CHT {
		TreeSet<Line> hull;
		int type;  boolean query  = false;
		Comparator<Line> comp = new Comparator<Line>() {
			public int compare(Line a, Line b) {
				if (!query) return type * Long.compare(a.m, b.m);
				if (a.left == b.left) return Long.compare(a.m, b.m);
				return Double.compare(a.left, b.left);
			}
		};
		// -1 for min; +1 for max
		public CHT(int typee) { type = typee;  hull = new TreeSet<>(comp); }

		public void add(long m, long b) { add(new Line(m, b)); }

		public void add(Line a) {
			Line[] LR = { hull.lower(a), hull.ceiling(a) };
			for (int i = 0; i < 2; i++)
				if (LR[i] != null && LR[i].m == a.m) {
					if (type == 1 && LR[i].b >= a.b) return;
					if (type == -1 && LR[i].b <= a.b) return;
					remove(LR[i]);
				}
			hull.add(a);
			Line L = hull.lower(a), R = hull.higher(a);
			if (L != null && R != null && a.inter(R) <= R.left) {
				hull.remove(a);
				return;
			}
			Line LL = (L != null) ? hull.lower(L) : null;
			Line RR = (R != null) ? hull.higher(R) : null;
			if (L != null) a.left = a.inter(L);
			if (R != null) R.left = a.inter(R);
			while (LL != null && L.left >= a.inter(LL)) {
				remove(L);
				a.left = a.inter(L = LL);
				LL = hull.lower(L);
			}
			while (RR != null && R.inter(RR) <= a.inter(RR)) {
				remove(R);
				RR.left = a.inter(R = RR);
				RR = hull.higher(R);
			}
		}

		public long query(long x) {
			if(hull.size() == 0) return 0;
			Line temp = new Line(0, 0, 0);
			temp.left = x;  query = true;
			long ans = (long) hull.floor(temp).eval(x);
			query = false;  return ans;
		}

		private void remove(Line x) { hull.remove(x); }

		public int size() { return hull.size(); }

		static class Line {
			long m, b; double left = Long.MIN_VALUE;
			public Line(long mm, long x, long y) { m = mm; b = -m * x + y; }
			public Line(long mm, long bb) { m = mm; b = bb; }
			public long eval(long x) { return m * x + b; }
			public double inter(Line x) {
				return (double) (x.b - this.b) / (double) (this.m - x.m);
			}
		}
	}

	static class FS{
		BufferedReader br;
		StringTokenizer st;
		public FS() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}
		String next() {
			while(st == null || !st.hasMoreElements()) {
				try {st = new StringTokenizer(br.readLine());}
				catch(Exception e) { throw null;}
			}
			return st.nextToken();
		}
		int nextInt() { return Integer.parseInt(next());}
		double nextDouble() { return Double.parseDouble(next());}
		long nextLong() { return Long.parseLong(next());}
		int[] NIA(int n) {
			int r[] = new int[n];
			for(int i = 0; i < n; i++) r[i] = nextInt();
			return r;
		}
		long[] NLA(int n) {
			long r[] = new long[n];
			for(int i = 0; i < n; i++) r[i] = nextLong();
			return r;
		}
		char[][] grid(int r, int c){
			char res[][] = new char[r][c];
			for(int i = 0; i < r; i++) {
				char l[] = next().toCharArray();
				for(int j = 0; j < c; j++) {
					res[i][j] = l[j];
				}
			}
			return res;
		}
	}

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.StringTokenizer;
public class  Main {
    static class MyScanner {
        BufferedReader br;
        StringTokenizer st;

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

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

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

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

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

        public String nextLine(){
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }

   static MyScanner s=new MyScanner();

   public static int process(int a,int k) {
	   long ans=1;
	   for(int i=0;i<a;i++)ans*=10;
	   return (int)ans%k;
   }
   static int[]arr=new int[100010];
   static int mod=(int)1e9+7;
  static  {
	   arr[0]=1;
	   for(int i=1;i<=100000;i++) {
		   arr[i]=((arr[i-1]%mod)*2)%mod;
	   }
   }
  static class Info{
      int x;int y;
      public Info(){}
      public Info(int x,int y){
          this.x=x;this.y=y;
      }
  }
  public static Info exgcd(int a,int b){
      if(b==0){
          return new Info(1,0);
      }
      Info info=exgcd(b,a%b);
      return new Info(info.y,info.x-a/b*info.y);
  }
public static void main(String[] args) {
int K=1;
int N=10,M=10;
while(K>0) {
    int n=s.nextInt(),k=s.nextInt();
    if(k>=n){
        System.out.println(arr[n]);
        break;
        }
    long cur=1,ans=cur;
    for(int i=1;i<=k;i++) {
    	cur=cur%mod*(n-i+1)%mod;
    	cur%=mod;
    	if(cur%i==0) {
    		cur/=i;
    	}
    	else {
    		Info info=exgcd(i,mod);
    		cur=cur%mod*(info.x)%mod;
    		cur%=mod;
    	}
    	ans=ans%mod+cur%mod;
    	ans%=mod;
    }
    System.out.println((ans+mod)%mod);
	K--;
}
}
}


//package javaapplication88;
import java.util.*;
public class JavaApplication88
{

    public static void main(String[] args)
    {
        Scanner sc=new Scanner(System.in);
        String a=sc.next();
        String b=sc.next();
        int count1=0,count2=0,count3=0;
        for(int i=0;i<a.length();i++)
        {
            if(a.charAt(i) == '+')
            {
                count1++;
            }
        }
        for(int i=0;i<b.length();i++)
        {
            if(b.charAt(i)=='+')
            {
                count2++;
            }
            else if(b.charAt(i)=='?')
            {
                count3++;
            }
        }
        if(count1==count2 && count3==0)
        {
            System.out.println(1);
        }
        else if(count3==0 && count1!=count2)
        {
            System.out.println(0);
        }
        else if(count1==count2 && count3!=0)
        {
           // System.out.println("hi");
            double ans;
             if(count1 ==0)
            {

                ans=1;
                ans=(double)(ans/Math.pow(2, count3));
            }
           else if(count3%2==0)
            {
                 ans=fact(count3)/(fact((count3/2))*fact((count3/2))) + 1;
                 ans=(double) (ans/Math.pow(2, count3));
            }

            else
            {
                ans=1;
                ans=(double)(ans/Math.pow(2, count3));
            }

            System.out.println(ans);
        }

        else if(count2+count3 >=count1)
        {
            //System.out.println("hi");
            double ans;
            if((count2+count3)==count1)
            {
                ans=1;

            }

            else
            {
                if(count1 - count2 >0)
                    ans=fact(count3)/(fact(count1-count2)*fact(count3+count2-count1));
                else
                    ans=0;

            }
            ans=(double) (ans/Math.pow(2, count3));
            System.out.print(ans);
        }
        else
        {
            System.out.println(0);
        }
    }
     static double fact(int n)
    {
        double ans=1;
        if(n==0)
            return 1;
        for(int i=n;i>0;i--)
        {

            ans=ans*i;
        }
        return ans;
    }

}


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

public class contet1 {
	public static void main(String[]args){
		Scanner scan = new Scanner(System.in);{
			int runs = scan.nextInt();
			int a = scan.nextInt();
			int b = scan.nextInt();
			int[] arr = new int[runs];
			int totalmin = 0;
			for(int i =0;i<runs;i++){
				arr[i]=scan.nextInt();
			}
			Arrays.sort(arr);
			for(int i = 0;i<arr.length-a;i++){
				totalmin+=arr[i];
			}
			System.out.println(totalmin+(a*b));
		}
	}
}


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Comparator;
import java.util.TreeSet;

public class E {
    private static StreamTokenizer in;
    private static PrintWriter out;
    private static BufferedReader inB;

    private static int nextInt() throws Exception{
        in.nextToken();
        return (int)in.nval;
    }

    private static String nextString() throws Exception{
        in.nextToken();
        return in.sval;
    }

    static{
        inB = new BufferedReader(new InputStreamReader(System.in));
        in = new StreamTokenizer(inB);
        out = new PrintWriter(System.out);
    }

    public static void main(String[] args)throws Exception {
        Complex A = new Complex(nextInt(), nextInt());
        Complex B = new Complex(nextInt(), nextInt());
        Complex C = new Complex(nextInt(), nextInt());

        boolean was = false;
        for(int i = 0; i<4; i++) {
            Complex cur = B.sub(A.mul(powi(i)));
            if(C.equals(Complex.z)) {
                if(cur.equals(Complex.z))was = true;
            } else {
                if(check(cur, C))was = true;
            }
        }

        System.out.println(was ? "YES" : "NO");
    }

    private static Complex powi(int n) {
        Complex ans = new Complex(1, 0);
        for(int i = 0; i<n; i++) {
            ans = ans.mul(Complex.i);
        }
        return ans;
    }

    private static boolean check(Complex cur, Complex C) {
        Complex tmp = cur.mul(new Complex(C.x, -C.y));
        long m = C.mod();
        return tmp.x % m == 0 && tmp.y % m == 0;
    }
}

class Complex {
    long x, y;

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

    Complex add(Complex c) {
        return new Complex(c.x + x, c.y + y);
    }

    Complex mul(Complex c) {
        return new Complex(c.x*x - c.y*y, c.x*y + c.y*x);
    }

    Complex sub(Complex c) {
        return add(c.mul(new Complex(-1,0)));
    }

    boolean equals(Complex c) {
        return x == c.x && y == c.y;
    }

    long mod() {
        return x*x + y*y;
    }

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

    public static final Complex i = new Complex(0, 1);
    public static final Complex z = new Complex(0, 0);
}


import java.util.Scanner;
public class code {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
      //  int t = sc.nextInt();
      //  while(t-- != 0){
           int n = sc.nextInt();

            System.out.println(n+1);
       // }
    }
}


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

public class a302
{
	public static void main(String[] args) throws Exception
	{
		InputReader in = new InputReader(System.in);
		OutputWriter out = new OutputWriter(System.out);
		int n=in.readInt();
		String s=in.readString();
		if(n==1)
		{
			out.printLine("YES");
			out.printLine(s);
		}
		else
		{
			char ch[]=new char[n];
			String c[]=new String[n];
			ch[0]=s.charAt(0);
			int k=0,index=0,i;
			int flag=0;
			for(i=1;i<s.length();i++)
			{
				flag=0;
				for(int j=0;j<=k;j++)
					if(s.charAt(i)==ch[j])
						flag=1;
				if(flag==0&&k+1==n-1)
				{
					c[k]=s.substring(index,i);
					k+=1;
					c[k]=s.substring(i);
				}
				else if(flag==0&&k+2<n)
				{
					c[k]=s.substring(index,i);
					k+=1;
					index=i;
					ch[k]=s.charAt(i);
				}
			}
			if (c[n-1]!=null)
			{
				out.printLine("YES");
				for(int j=0;j<n;j++)
					out.printLine(c[j]);
			}
			else
			out.printLine("NO");
		}

		out.close();
	}

	private static class InputReader
	{
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;
		private SpaceCharFilter filter;

		public InputReader(InputStream stream)
		{
			this.stream = stream;
		}

		public int read()
		{
			if (numChars == -1)
				throw new InputMismatchException();
			if (curChar >= numChars)
			{
				curChar = 0;
				try
				{
					numChars = stream.read(buf);
				} catch (IOException e)
				{
					throw new InputMismatchException();
				}
				if (numChars <= 0)
				return -1;
			}
			return buf[curChar++];
		}
		public int readInt()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-')
			{
				sgn = -1;
				c = read();
			}
			int res = 0;
			do
			{
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			return res * sgn;
		}
		public String readString()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do
			{
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public boolean isSpaceChar(int c)
		{
			if (filter != null)
				return filter.isSpaceChar(c);
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		public interface SpaceCharFilter
		{
			public boolean isSpaceChar(int ch);
		}
	}

	private static class OutputWriter
	{
		private final PrintWriter writer;

		public OutputWriter(OutputStream outputStream)
		{
			writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
		}

		public OutputWriter(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 printLine(Object... objects)
		{
			print(objects);
			writer.println();
		}

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

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

	}
}


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

public class Main {

    public static void main(String[] args) throws Exception {
        FastReader fr = new FastReader();
        long n = fr.nextInt();
        long a = fr.nextInt();
        long b = fr.nextInt();
        long c = fr.nextInt();
        switch ((int) (4 - n % 4)) {
            case 1:
                    System.out.println(Math.min(a, Math.min(b+c, 3*c)));
                break;
            case 2:
                    System.out.println(Math.min(a*2, Math.min(b, 2*c)));
                break;
            case 3:
                    System.out.println(Math.min(a*3, Math.min(b + a, c)));
                break;
            default:
                    System.out.println(0);
                break;
        }
    }

}

class FastReader {
    final private int BUFFER_SIZE = 1 << 16;
    private DataInputStream din;
    private byte[] buffer;
    private int bufferPointer, bytesRead;

    public FastReader() {
        din = new DataInputStream(System.in);
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public FastReader(String file_name) throws IOException {
        din = new DataInputStream(new FileInputStream(file_name));
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public String readLine() throws IOException {
        byte[] buf = new byte[64]; // line length
        int cnt = 0, c;
        while ((c = read()) != -1) {
            if (c == '\n')
                break;
            buf[cnt++] = (byte) c;
        }
        return new String(buf, 0, cnt);
    }

    public int nextInt() throws IOException {
        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 long nextLong() throws IOException {
        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 double nextDouble() throws IOException {
        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() throws IOException {
        if (bufferPointer == bytesRead)
            fillBuffer();
        return buffer[bufferPointer++];
    }

    public void close() throws IOException {
        if (din == null)
            return;
        din.close();
    }
}


//package round429;
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 C2 {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni();
		int[] a = na(n);
		for(int i = 0;i < n;i++){
			int v = a[i];
			for(int j = 2;j*j <= v;j++){
				while(v % (j*j) == 0){
					v /= j*j;
				}
			}
			a[i] = v;
		}

		Arrays.sort(a);
		int[] f = new int[n];
		int p = 0;
		for(int i= 0;i < n;i++){
			if(i > 0 && a[i] != a[i-1]){
				p++;
			}
			f[p]++;
		}
		f = Arrays.copyOf(f, p+1);
		int mod = 1000000007;

		int[][] fif = enumFIF(1000, mod);
		long[] res = countSameNeighborsSequence(f, fif, mod);
		long ans = res[0];
		for(int v : f){
			ans = ans * fif[0][v] % mod;
		}

		out.println(ans);
	}

	public static int[][] enumFIF(int n, int mod) {
		int[] f = new int[n + 1];
		int[] invf = new int[n + 1];
		f[0] = 1;
		for (int i = 1; i <= n; i++) {
			f[i] = (int) ((long) f[i - 1] * i % mod);
		}
		long a = f[n];
		long b = mod;
		long p = 1, q = 0;
		while (b > 0) {
			long c = a / b;
			long d;
			d = a;
			a = b;
			b = d % b;
			d = p;
			p = q;
			q = d - c * q;
		}
		invf[n] = (int) (p < 0 ? p + mod : p);
		for (int i = n - 1; i >= 0; i--) {
			invf[i] = (int) ((long) invf[i + 1] * (i + 1) % mod);
		}
		return new int[][] { f, invf };
	}

	public static long[] countSameNeighborsSequence(int[] a, int[][] fif, int mod)
	{
		int n = a.length;

		int bef = a[0];
		int aft = a[0];
		long[] dp = new long[bef];
		dp[bef-1] = 1;
		for(int u = 1;u < n;u++){
			int v = a[u];
			aft += v;
			long[][] ldp = new long[bef][aft];
			for(int i = 0;i < dp.length;i++){
				ldp[i][0] = dp[i];
			}

			for(int i = 0;i < v;i++){
				long[][] ndp = new long[bef][aft];
				for(int j = 0;j < bef;j++){
					for(int k = 0;j+k < aft;k++){
						if(ldp[j][k] == 0)continue;
						// XX -> XCX
						if(j > 0){
							ndp[j-1][k] += ldp[j][k] * j;
							ndp[j-1][k] %= mod;
						}

						// CC -> CCC
						if(k > 0){
							ndp[j][k+1] += ldp[j][k] * k;
							ndp[j][k+1] %= mod;
						}

						// XC -> XCC
						// #XC = 2*(i-k)
						if(2*(i-k) > 0){
							ndp[j][k+1] += ldp[j][k] * (2*(i-k));
							ndp[j][k+1] %= mod;
						}

						// XY -> XCY
						// #XY = bef+i+1-#XC-#CC-#XX
						if(bef+i+1-j-k-2*(i-k) > 0){
							ndp[j][k] += ldp[j][k] * (bef+i+1-j-k-2*(i-k));
							ndp[j][k] %= mod;
						}
					}
				}
				ldp = ndp;
			}

			dp = new long[aft];
			for(int j = 0;j < bef;j++){
				for(int k = 0;j+k < aft;k++){
					dp[j+k] += ldp[j][k];
					if(dp[j+k] >= mod)dp[j+k] -= mod;
				}
			}
			for(int j = 0;j < aft;j++)dp[j] = dp[j] * fif[1][v] % mod;
			bef = aft;
		}
		return dp;
	}

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