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


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.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
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);
        OutputWriter out = new OutputWriter(outputStream);
        TaskC solver = new TaskC();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskC {
        public void solve(int testNumber, InputReader in, OutputWriter out) {
            int n = in.nextInt(), r = in.nextInt();
            int[] f = new int[n], s = new int[n];
            double[] p = new double[n];
            int[] g = new int[n];
            int sum = 0;
            int sf = 0;
            for (int i = 0; i < n; i++) {
                f[i] = in.nextInt();
                s[i] = in.nextInt();
                p[i] = in.nextInt() / 100.0;
                g[i] = s[i] - f[i];
                sum += s[i];
                sf += f[i];
            }
            int needg = (sum - r);
            double lo = sf, hi = 1L << 50;
            for (int iter = 0; iter < 80; iter++) {
                double mid = (lo + hi) / 2.0;
                double[][] dp = new double[n + 1][needg + 1];
                for (int i = 0; i < needg; i++) {
                    dp[n][i] = mid;
                }
                dp[n][needg] = 0;
                for (int i = n - 1; i >= 0; i--) {
                    for (int have = 0; have <= needg; have++) {
                        // restart, try level
                        int nhave = Math.min(needg, have + g[i]);
                        dp[i][have] = Math.min(mid, (dp[i + 1][nhave] + f[i]) * p[i] + (1 - p[i]) * (dp[i + 1][have] + s[i]));
                    }
                }

                if (dp[0][0] < mid) {
                    hi = mid;
                } else {
                    lo = mid;
                }
            }
            out.printf("%.10f\n", (lo + hi) / 2.0);
        }

    }

    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 printf(String format, Object... objects) {
            writer.printf(format, objects);
        }

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

    }

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

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

        public int read() {
            if (this.numChars == -1) {
                throw new InputMismatchException();
            } else {
                if (this.curChar >= this.numChars) {
                    this.curChar = 0;

                    try {
                        this.numChars = this.stream.read(this.buf);
                    } catch (IOException var2) {
                        throw new InputMismatchException();
                    }

                    if (this.numChars <= 0) {
                        return -1;
                    }
                }

                return this.buf[this.curChar++];
            }
        }

        public int nextInt() {
            int c;
            for (c = this.read(); isSpaceChar(c); c = this.read()) {
                ;
            }

            byte sgn = 1;
            if (c == 45) {
                sgn = -1;
                c = this.read();
            }

            int res = 0;

            while (c >= 48 && c <= 57) {
                res *= 10;
                res += c - 48;
                c = this.read();
                if (isSpaceChar(c)) {
                    return res * sgn;
                }
            }

            throw new InputMismatchException();
        }

        public static boolean isSpaceChar(int c) {
            return c == 32 || c == 10 || c == 13 || c == 9 || c == -1;
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.io.IOException;
import java.util.Random;
import java.io.UncheckedIOException;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

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

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

    static class CPrairiePartition {
        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.readInt();
            long[] a = new long[n];
            int[] cnts = new int[50];
            LongList special = new LongList(n);

            in.populate(a);
            for (long x : a) {
                if (Long.lowestOneBit(x) == x) {
                    cnts[Log2.floorLog(x)]++;
                } else {
                    special.add(x);
                }
            }
            special.sort();

            IntBinarySearch ibs = new IntBinarySearch() {

                public boolean check(int mid) {
                    int one = cnts[0] - mid;
                    int specialIndex = 0;

                    int flow = mid;
                    int taged = 0;
                    for (int i = 1; i < cnts.length; i++) {
                        int c = cnts[i];
                        if (c <= flow) {
                            int kickOut = flow - c;
                            int kickTaged = Math.min(taged, kickOut);
                            taged -= kickTaged;
                            int kickUnTaged = kickOut - kickTaged;
                            flow -= kickOut;

                            while (kickUnTaged > 0 && specialIndex < special.size() &&
                                    special.get(specialIndex) <= (1L << i)) {
                                kickUnTaged--;
                                specialIndex++;
                            }
                            while (kickUnTaged > 0 && one > 0) {
                                kickUnTaged--;
                                one--;
                            }
                        } else {
                            c -= flow;
                            taged += c;
                        }
                    }

                    int kickOut = flow - taged;
                    return kickOut >= special.size() - specialIndex + one;
                }
            };

            int ans = ibs.binarySearch(0, cnts[0]);
            if (!ibs.check(ans)) {
                out.println(-1);
                return;
            }

            for (int i = ans; i <= cnts[0]; i++) {
                out.append(i).append(' ');
            }
        }

    }

    static class FastOutput implements AutoCloseable, Closeable, Appendable {
        private StringBuilder cache = new StringBuilder(10 << 20);
        private final Writer os;

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

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

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

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

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

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

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

        public FastOutput println() {
            cache.append(System.lineSeparator());
            return this;
        }

        public FastOutput flush() {
            try {
                os.append(cache);
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

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

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

    }

    static class SequenceUtils {
        public static boolean equal(long[] a, int al, int ar, long[] b, int bl, int br) {
            if ((ar - al) != (br - bl)) {
                return false;
            }
            for (int i = al, j = bl; i <= ar; i++, j++) {
                if (a[i] != b[j]) {
                    return false;
                }
            }
            return true;
        }

    }

    static class LongList implements Cloneable {
        private int size;
        private int cap;
        private long[] data;
        private static final long[] EMPTY = new long[0];

        public LongList(int cap) {
            this.cap = cap;
            if (cap == 0) {
                data = EMPTY;
            } else {
                data = new long[cap];
            }
        }

        public LongList(LongList list) {
            this.size = list.size;
            this.cap = list.cap;
            this.data = Arrays.copyOf(list.data, size);
        }

        public LongList() {
            this(0);
        }

        public void ensureSpace(int req) {
            if (req > cap) {
                while (cap < req) {
                    cap = Math.max(cap + 10, 2 * cap);
                }
                data = Arrays.copyOf(data, cap);
            }
        }

        private void checkRange(int i) {
            if (i < 0 || i >= size) {
                throw new ArrayIndexOutOfBoundsException();
            }
        }

        public long get(int i) {
            checkRange(i);
            return data[i];
        }

        public void add(long x) {
            ensureSpace(size + 1);
            data[size++] = x;
        }

        public void addAll(long[] x, int offset, int len) {
            ensureSpace(size + len);
            System.arraycopy(x, offset, data, size, len);
            size += len;
        }

        public void addAll(LongList list) {
            addAll(list.data, 0, list.size);
        }

        public void sort() {
            if (size <= 1) {
                return;
            }
            Randomized.shuffle(data, 0, size);
            Arrays.sort(data, 0, size);
        }

        public int size() {
            return size;
        }

        public long[] toArray() {
            return Arrays.copyOf(data, size);
        }

        public String toString() {
            return Arrays.toString(toArray());
        }

        public boolean equals(Object obj) {
            if (!(obj instanceof LongList)) {
                return false;
            }
            LongList other = (LongList) obj;
            return SequenceUtils.equal(data, 0, size - 1, other.data, 0, other.size - 1);
        }

        public int hashCode() {
            int h = 1;
            for (int i = 0; i < size; i++) {
                h = h * 31 + Long.hashCode(data[i]);
            }
            return h;
        }

        public LongList clone() {
            LongList ans = new LongList();
            ans.addAll(this);
            return ans;
        }

    }

    static class RandomWrapper {
        private Random random;
        public static RandomWrapper INSTANCE = new RandomWrapper(new Random());

        public RandomWrapper() {
            this(new Random());
        }

        public RandomWrapper(Random random) {
            this.random = random;
        }

        public int nextInt(int l, int r) {
            return random.nextInt(r - l + 1) + l;
        }

    }

    static abstract class IntBinarySearch {
        public abstract boolean check(int mid);

        public int binarySearch(int l, int r) {
            if (l > r) {
                throw new IllegalArgumentException();
            }
            while (l < r) {
                int mid = DigitUtils.floorAverage(l, r);
                if (check(mid)) {
                    r = mid;
                } else {
                    l = mid + 1;
                }
            }
            return l;
        }

    }

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

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

        public void populate(long[] data) {
            for (int i = 0; i < data.length; i++) {
                data[i] = readLong();
            }
        }

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

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

        public int readInt() {
            int sign = 1;

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

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

            return val;
        }

        public long readLong() {
            int sign = 1;

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

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

            return val;
        }

    }

    static class DigitUtils {
        private DigitUtils() {
        }

        public static int floorAverage(int x, int y) {
            return (x & y) + ((x ^ y) >> 1);
        }

    }

    static class Randomized {
        public static void shuffle(long[] data, int from, int to) {
            to--;
            for (int i = from; i <= to; i++) {
                int s = nextInt(i, to);
                long tmp = data[i];
                data[i] = data[s];
                data[s] = tmp;
            }
        }

        public static int nextInt(int l, int r) {
            return RandomWrapper.INSTANCE.nextInt(l, r);
        }

    }

    static class Log2 {
        public static int floorLog(long x) {
            return 63 - Long.numberOfLeadingZeros(x);
        }

    }
}


//package arbuz;

import java.util.Scanner;

public class Arbuz {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] first = new int[n];
        int[] second = new int[n];
        int i;
        String s = sc.next();
        for (i = 0; i < n; i++) {
            first[i] = (byte) s.charAt(i) - 48;
            second[i] = (byte) s.charAt(n + i) - 48;
        }
        i = 0;
        while (i < n - 1) {
            if (first[i] > first[i + 1]) {
                int temp = first[i];
                first[i] = first[i + 1];
                first[i + 1] = temp;
                i = -1;
            }
            i++;
        }
        i = 0;
        while (i < n - 1) {
            if (second[i] > second[i + 1]) {
                int temp = second[i];
                second[i] = second[i + 1];
                second[i + 1] = temp;
                i = -1;
            }
            i++;
        }
        boolean less = false, bigger = false, equal = false, match = true;
        for (i = 0; i < n; i++) {
            if (first[i] == second[i]) {
                equal = true;
            }
            if (first[i] < second[i]) {
                less = true;
            }
            if (first[i] > second[i]) {
                bigger = true;
            }
            if ((less && bigger) || equal) {
                match = false;
                break;
            }
        }
        if (match) {
            System.out.println("YES");
        } else {
            System.out.println("NO");
        }
    }
}


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

public class D {

	static final int INF = Integer.MAX_VALUE / 10;
	BufferedReader br;
	PrintWriter out;
	StringTokenizer st;
	boolean eof;

	int[] v1, v2;
	int[][] g;
	int[][] d;

	int n, m;

	int[] deg;

	double[] ps;
	int[] psList;
	int psPtr = 0;

	double[] maxP;
	int[] maxPList;
	int maxPPtr = 0;

	double go2(Integer[] vs, int from, int to) {
		double stupid = 1.0 / (to - from);

		double smart = 0;

		for (int i = from; i < to; i++) {

			int v = vs[i];

			for (int j = 0; j < deg[v]; j++) {
				int u = g[v][j];
				if (ps[u] < 0) {
					ps[u] = 0;
					psList[psPtr++] = u;
				}
				ps[u] += stupid / deg[v];
			}

		}

		for (int v2 = 0; v2 < n; v2++) {
			for (int i = 0; i < psPtr; i++) {
				int u = psList[i];
				int dst = d[v2][u];
				if (maxP[dst] < 0) {
					maxP[dst] = 0;
					maxPList[maxPPtr++] = dst;
				}
				maxP[dst] = Math.max(maxP[dst], ps[u]);
			}
			double here = 0;
			for (int i = 0; i < maxPPtr; i++) {
				here += maxP[maxPList[i]];
			}
			smart = Math.max(smart, here);

			while (maxPPtr > 0) {
				int v = maxPList[--maxPPtr];
				maxP[v] = -1;
			}
		}

		while (psPtr > 0) {
			int v = psList[--psPtr];
			ps[v] = -1;
		}

//		System.err.println(from + " " + to + " -> " + smart + " " + stupid);

		return Math.max(smart, stupid);

	}

	double go(int v) {
		final int[] dist = d[v];
		Integer[] a = new Integer[n];
		for (int i = 0; i < n; i++) {
			a[i] = i;
		}
		Arrays.sort(a, new Comparator<Integer>() {

			@Override
			public int compare(Integer o1, Integer o2) {
				return Integer.compare(dist[o1], dist[o2]);
			}

		});

		double ret = 0;

		for (int i = 0; i < n;) {
			int j = i;
			while (j < n && dist[a[i]] == dist[a[j]]) {
				j++;
			}

			ret += 1.0 * (j - i) / n * go2(a, i, j);
			i = j;
		}

		return ret;
	}

	void solve() throws IOException {
		n = nextInt();
		m = nextInt();

		v1 = new int[m];
		v2 = new int[m];
		deg = new int[n];

		d = new int[n][n];
		for (int i = 0; i < n; i++) {
			Arrays.fill(d[i], INF);
			d[i][i] = 0;
		}

		for (int i = 0; i < m; i++) {
			v1[i] = nextInt() - 1;
			v2[i] = nextInt() - 1;
			d[v1[i]][v2[i]] = d[v2[i]][v1[i]] = 1;
			deg[v1[i]]++;
			deg[v2[i]]++;
		}

		g = new int[n][];
		for (int i = 0; i < n; i++) {
			g[i] = new int[deg[i]];
		}

		int[] ptrDeg = deg.clone();

		for (int i = 0; i < m; i++) {
			int v = v1[i];
			int u = v2[i];
			g[v][--ptrDeg[v]] = u;
			g[u][--ptrDeg[u]] = v;
		}

		for (int k = 0; k < n; k++)
			for (int i = 0; i < n; i++)
				for (int j = 0; j < n; j++) {
					d[i][j] = Math.min(d[i][j], d[i][k] + d[k][j]);
				}

		ps = new double[n];
		Arrays.fill(ps, -1);
		psList = new int[n];

		maxP = new double[n];
		Arrays.fill(maxP, -1);
		maxPList = new int[n];

		double ans = 0;
		for (int i = 0; i < n; i++) { // !!!
			ans = Math.max(ans, go(i));
		}

		out.println(ans);

	}

	D() throws IOException {
		br = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		solve();
		out.close();
	}

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

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

	String nextString() {
		try {
			return br.readLine();
		} catch (IOException e) {
			eof = true;
			return null;
		}
	}

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

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

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


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.Scanner;

public class Main {

    private static class Node {
        int HH;
        int MM;

        public Node(int h, int m) {
            this.HH = h;
            this.MM = m;
        }

        public static Node getNode(String s) {
            String[] w = s.split(":");
            int h = Integer.valueOf(w[0]);
            int m = Integer.valueOf(w[1]);

            return new Node(h, m);
        }

        private static int distanceInMinutes(Node s, Node e) {
            int d = getTotalMinutes(e) - getTotalMinutes(s);
            return d;
        }

        private static int getTotalMinutes(Node n) {

            return (n.HH * 60) + n.MM;
        }

        private static void addMinutes(Node n, int m) {

            n.MM += m;
            while (n.MM > 59) {
                n.MM = n.MM - 60;
                n.HH += 1;
            }
        }

        public static void output(Node sNode, Node eNode) {

            int d = Node.distanceInMinutes(sNode, eNode);

            Node.addMinutes(sNode, d / 2);

            String ms = String.valueOf(sNode.MM);
            if (sNode.MM < 10) {
                ms = String.valueOf("0" + sNode.MM);
            }

            String hs = String.valueOf(sNode.HH);
            if (sNode.HH < 10) {
                hs = String.valueOf("0" + sNode.HH);
            }
            System.out.println(hs + ":" + ms);
        }

        @Override
        public String toString() {
            return "Node{" +
                    "HH=" + HH +
                    ", MM=" + MM +
                    '}';
        }
    }

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

        String s = I.nextLine();
        String e = I.nextLine();

        Node sNode = Node.getNode(s);
        Node eNode = Node.getNode(e);

        Node.output(sNode, eNode);

    }

}


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

public class Main {

	static AReader scan = new AReader();
	static StringBuffer sb = new StringBuffer();
	static int N = 200010;
	static int MOD = (int)1e9+7;
	static long[] f = new long[N];
	static long[] g = new long[N];

	static void init(){
		f[0] = g[0] = 1;
		for(int i = 1;i<N;i++){
			f[i] = f[i-1] * i % MOD;
			g[i] = g[i-1] * qmi(i,MOD-2) % MOD;
		}
	}

	static long qmi(long a,int b){
		long res = 1;
		while(b>0){
			if((b & 1) == 1){
				res = res * a % MOD;
			}
			a = a * a % MOD;
			b >>=1;
		}
		return res % MOD;
	}

	static long C(int a,int b){
		return f[a] * g[b] % MOD * g[a-b] % MOD;
	}
	static void solve() {
		int n = scan.nextInt();
		int k = scan.nextInt();
		if(k == 0){
			System.out.println(1);
			return;
		}
		if(n % 2 == 1){
			long res = 0;
			// 枚举选几个1
			long t = 0;
			for(int i = 0;i<=n;i+=2){
				t = (t + C(n,i)) % MOD;
			}
			res = qmi(t + 1,k);
			System.out.println(res);
		}else{
			// 偶数情况
			long res = 0;

			long t = 0;
			// 每一位必须选偶数个1
			for(int i = 0;i<n;i+=2){
				t = (t + C(n,i)) % MOD;
			}

			// 左大于右 第i位左式为1 右式为0 前i位都是1 后面随便选
			for(int i = 1;i<=k;i++){
				res += qmi(t,i-1) * qmi(qmi(2,n),k-i) % MOD;
				res %=MOD;
			}

			res = (res + qmi(t,k)) % MOD;

			//res %= MOD;
			System.out.println(res);
		}

	}

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

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

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

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

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

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

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

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

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

class Pair {
	int x,y;

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


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

public class Main {

	static InputReader in = new InputReader(System.in);
	static PrintWriter out = new PrintWriter(System.out);

	static int oo = (int)1e9;
//	static long oo = (long)1e15;
	static int mod = 1_000_000_007;

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

	static int M = 5001;
	static double EPS = 1e-13;
	static int num = 1;

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

		long n = in.nextLong();
		long m = in.nextLong();
		int k = in.nextInt();
		if(k == -1 && n % 2 != m % 2) {
			System.out.println(0);
		}
		else {
			long x = pow(2, m-1, mod);
			long y = pow(x, n-1, mod);
			System.out.println(y);
		}

		out.close();
	}

	static int find(int[] g, int x) {
		return g[x] = g[x] == x ? x : find(g, g[x]);
	}

	static void union(int[] g, int[] size, int x, int y) {
		x = find(g, x); y = find(g, y);
		if(x == y)
			return;
		if(size[x] < size[y]) {
			g[x] = y;
			size[y] += size[x];
		}
		else {
			g[y] = x;
			size[x] += size[y];
		}
	}

	static class Segment {
		Segment left, right;
		int size, minIdx;
//		int time, lazy;

		public Segment(int[] a, int l, int r) {
			super();
			if(l == r) {
				this.minIdx = l;
				this.size = 1;
				return;
			}
			int mid = (l + r) / 2;
			left = new Segment(a, l, mid);
			right = new Segment(a, mid+1, r);
			if(a[left.minIdx] <= a[right.minIdx])
				this.minIdx = left.minIdx;
			else
				this.minIdx = right.minIdx;
			this.size = left.size + right.size;
		}

		boolean covered(int ll, int rr, int l, int r) {
			return ll <= l && rr >= r;
		}

		boolean noIntersection(int ll, int rr, int l, int r) {
			return ll > r || rr < l;
		}

//		void lazyPropagation() {
//			if(lazy != 0) {
//				if(left != null) {
//					left.setLazy(this.time, this.lazy);
//					right.setLazy(this.time, this.lazy);
//				}
//				else {
//					val = lazy;
//				}
//			}
//		}

//		void setLazy(int time, int lazy) {
//			if(this.time != 0 && this.time <= time)
//				return;
//			this.time = time;
//			this.lazy = lazy;
//		}

		int querySize(int ll, int rr, int l, int r) {
//			lazyPropagation();
			if(noIntersection(ll, rr, l, r))
				return 0;
			if(covered(ll, rr, l, r))
				return size;
			int mid = (l + r) / 2;
			int leftSize = left.querySize(ll, rr, l, mid);
			int rightSize = right.querySize(ll, rr, mid+1, r);
			return leftSize + rightSize;
		}

		int query(int k, int l, int r) {
			Segment trace = this;
			while(l < r) {
				int mid = (l + r) / 2;
				if(trace.left.size > k) {
					trace = trace.left;
					r = mid;
				}
				else {
					k -= trace.left.size;
					trace = trace.right;
					l = mid + 1;
				}
			}
			return l;
		}

		void update(int ll, int rr, int l, int r) {
//			lazyPropagation();
			if(noIntersection(ll, rr, l, r))
				return;
			if(covered(ll, rr, l, r)) {
//				setLazy(time, knight);
				this.minIdx = -1;
				this.size = 0;
				return;
			}
			int mid = (l + r) / 2;
			left.update(ll, rr, l, mid);
			right.update(ll, rr, mid+1, r);
			this.size = left.size + right.size;
		}
	}

	static long pow(long a, long n, long mod) {
		if(n == 0)
			return 1;
		if(n % 2 == 1)
			return a * pow(a, n-1, mod) % mod;
		long x = pow(a, n / 2, mod);
		return x * x % mod;
	}

	static int[] getPi(char[] a) {
		int m = a.length;
		int j = 0;
		int[] pi = new int[m];
		for(int i = 1; i < m; ++i) {
			while(j > 0 && a[i] != a[j])
				j = pi[j-1];
			if(a[i] == a[j]) {
				pi[i] = j + 1;
				j++;
			}
		}
		return pi;
	}

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

	static BigInteger lcm2(long a, long b) {
		long g = gcd(a, b);
		BigInteger gg = BigInteger.valueOf(g);
		BigInteger aa = BigInteger.valueOf(a);
		BigInteger bb = BigInteger.valueOf(b);
		return aa.multiply(bb).divide(gg);
	}

	static boolean nextPermutation(int[] a) {
		for(int i = a.length - 2; i >= 0; --i) {
			if(a[i] < a[i+1]) {
				for(int j = a.length - 1; ; --j) {
					if(a[i] < a[j]) {
						int t = a[i];
						a[i] = a[j];
						a[j] = t;
						for(i++, j = a.length - 1; i < j; ++i, --j) {
							t = a[i];
							a[i] = a[j];
							a[j] = t;
						}
						return true;
					}
				}
			}
		}
		return false;
	}

	static void shuffle(Object[] a) {
		Random r = new Random();
		for(int i = a.length - 1; i > 0; --i) {
			int si = r.nextInt(i);
			Object t = a[si];
			a[si] = a[i];
			a[i] = t;
		}
	}

	static void shuffle(int[] a) {
		Random r = new Random();
		for(int i = a.length - 1; i > 0; --i) {
			int si = r.nextInt(i);
			int t = a[si];
			a[si] = a[i];
			a[i] = t;
		}
	}

	static void shuffle(long[] a) {
		Random r = new Random();
		for(int i = a.length - 1; i > 0; --i) {
			int si = r.nextInt(i);
			long t = a[si];
			a[si] = a[i];
			a[i] = t;
		}
	}

	static int lower_bound(int[] a, int n, int k) {
		int s = 0;
		int e = n;
		int m;
		while (e - s > 0) {
			m = (s + e) / 2;
			if (a[m] < k)
				s = m + 1;
			else
				e = m;
		}
		return e;
	}
	static int lower_bound(long[] a, int n, long k) {
		int s = 0;
		int e = n;
		int m;
		while (e - s > 0) {
			m = (s + e) / 2;
			if (a[m] < k)
				s = m + 1;
			else
				e = m;
		}
		return e;
	}

	static int gcd(int a, int b) {
		return b == 0 ? a : gcd(b, a % b);
	}
	static long gcd(long a, long b) {
		return b == 0 ? a : gcd(b, a % b);
	}
	static BigInteger gcd(BigInteger a, BigInteger b) {
		return b.compareTo(BigInteger.ZERO) == 0 ? a : gcd(b, a.mod(b));
	}

	static class Pair implements Comparable<Pair> {
		int first, second;

		public Pair(int first, int second) {
			super();
			this.first = first;
			this.second = second;
		}

		@Override
		public int compareTo(Pair o) {
			return this.first != o.first ? this.first - o.first : this.second - o.second;
		}

//		@Override
//		public int compareTo(Pair o) {
//			return this.first != o.first ? o.first - this.first : o.second - this.second;
//		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + first;
			result = prime * result + second;
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Pair other = (Pair) obj;
			if (first != other.first)
				return false;
			if (second != other.second)
				return false;
			return true;
		}
	}
}

class InputReader {

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

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

	public int read() {
		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 = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} 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 = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isSpaceChar(c));
		return res.toString();
	}

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

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

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}

}


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

//abzzzzzzzzabcdzzzzzzzcd
//abcd
public class D {
	private static int n, m;
	private static int[] a;
	private static String s, t;
	private static HashMap<Integer, ArrayList<Integer>> g;
	private static long pp, qq, rr;

	public static void main(String[] args) {
		s = ins();
		t = ins();
		n = s.length();
		m = t.length();
		int[][] mapRight = new int[n][26];
		for(int i=n-1; i>=0; i--) {
			for(int j=0; j<26; j++) {
				mapRight[i][j] = (i+1<n?mapRight[i+1][j]:-1);
			}
			mapRight[i][s.charAt(i)-'a'] = i;
		}
		int[][] mapLeft = new int[n][26];
		for(int i=0; i<n; i++) {
			for(int j=0; j<26; j++) {
				mapLeft[i][j] = (i-1>=0?mapLeft[i-1][j]:-1);
			}
			mapLeft[i][s.charAt(i)-'a'] = i;
		}

		//from right keep the highest index (to the right) which keeps the substring T[j:n]
		//map[j] = that index
		//so it is smallest index from right

		int done = m-1;

		int[] finalMap2 = new int[m];

		for(int i=n-1; i>=0; i--) {
			if (done==-1) {
				break;
			}
			if (s.charAt(i)==t.charAt(done)) {
				finalMap2[done] = i;
				done--;
			}
		}

		int[] finalMap1 = new int[m];
		done = 0;

		for(int i=0; i<n; i++) {
			if (done==m) break;
			if (s.charAt(i)==t.charAt(done)) {
				finalMap1[done] = i;
				done++;
			}
		}

		done = 0;

		int ans = 0;

		int i = 0;

		//i to j-1 -> j-1-i+1 -> j-i

		while(i<n) {
			ans = Math.max(ans, finalMap2[done]-i);
			i = finalMap1[done]+1;
			done++;
			if (done==m) {
				ans = Math.max(ans, n-1-i+1);
				break;
			}
		}

		println(ans);

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

	}

	//NONPROBLEM CODE

	private static InputReader in = new InputReader(System.in);
	private static PrintWriter out = new PrintWriter(System.out);

	private static class InputReader {

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

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

		public int read() {
			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 = read();
			while (isSpaceChar(c)) {
				c = read();
			}
			int sgn = 1;
			if (c == '-') {
				sgn = -1;
				c = read();
			}
			int res = 0;
			do {
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			return res * sgn;
		}

		public long nextLong() {
			int c = read();
			while (isSpaceChar(c)) {
				c = read();
			}
			int sgn = 1;
			if (c == '-') {
				sgn = -1;
				c = read();
			}
			long res = 0;
			do {
				res *= 10;
				res += c - '0';
				c = read();
			} 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 = read();
			while (isSpaceChar(c)) {
				c = read();
			}
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

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

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

		private boolean isEndOfLine(int c) {
			return c == '\n' || c == '\r' || c == -1;
		}

	}

	//INPUT SHORTCUTS

	private static int[] ina(int n) {
		int[] temp = new int[n];
		for (int i = 0; i < n; i++) {
			temp[i] = in.nextInt();
		}
		return temp;
	}

	private static int ini() {
		return in.nextInt();
	}

	private static String ins() {
		return in.readString();
	}

	//OTHER SHORTCUTS
	public static void sort(int[] a) {
		Arrays.sort(a);
	}

	//PRINT SHORTCUTS

	private static void println(Object... o) {
		for (Object x : o) {
			out.write(x + " ");
		}
		out.write("\n");
	}

	private static void print(Object... o) {
		for (Object x : o) {
			out.write(x + "");
		}
	}

	private static void printAll(Object... o) {
		for (Object x : o) {
			out.write(x + " ");
		}
	}

	private static void debug(Object... o) {
		for (Object x : o) {
			out.write(x + " ");
		}
		out.write("\n");
		out.flush();
	}

	private static HashMap<Integer, ArrayList<Integer>> intree(int n) {

		HashMap<Integer, ArrayList<Integer>> g = new HashMap<>();
		for (int i = 0; i < n; i++) {
			g.put(i, new ArrayList<>());
		}

		for (int i = 0; i < n - 1; i++) {
			int u = ini() - 1;
			int v = ini() - 1;
			g.get(u).add(v);
			g.get(v).add(u);
		}

		return g;
	}
}


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

public class CF797A{
  public static int index;
  public static void main(String[] args)throws Exception {
    InputReader in = new InputReader(System.in);
    PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
    int n = in.nextInt(), k = in.nextInt();

    ArrayList<Integer> list = new ArrayList<>();

    while(list.size() < k && n > 1){

      if(list.size() == k-1 && n > 1){
        list.add(n);
        n = 1;
        break;
      }

      for(int i = 2; i <= n; i++){
        if(n%i == 0) {
          list.add(i);
          n /= i;
          break;
        }
      }

    }

    if(list.size() < k || n != 1) pw.println(-1);
    else{
      for(int i : list) pw.print(i+" ");
      pw.println();
    }

    pw.close();
  }

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

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

    public String next()throws Exception {
      while (tokenizer == null || !tokenizer.hasMoreTokens())
        tokenizer = new StringTokenizer(reader.readLine());
      return tokenizer.nextToken();
    }

    public String nextLine()throws Exception {
      String line = null;
      tokenizer = null;
      line =  reader.readLine();
      return line;
    }

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

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

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

  }
}


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

public class D {

	static class Point {
		int x, y;

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

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

	void submit() {
		int n = nextInt();
		int nn = n;
		Point[] a = new Point[n];
		long sx = 0;
		long sy = 0;
		for (int i = 0; i < n; i++) {
			int x = nextInt() * 2;
			int y = nextInt() * 2;
			a[i] = new Point(x, y);
			sx += x;
			sy += y;
		}

		boolean[] mark = new boolean[n];

		for (int i = 0; i < n; i++) {
			long ix = 2 * sx - (long)n * a[i].x;
			long iy = 2 * sy - (long)n * a[i].y;
			for (int j = i; j < n; j++) {
				if ((long)n * a[j].x == ix && (long)n * a[j].y == iy) {
					mark[j] = mark[i] = true;
					break;
				}
			}
		}

		{
			Point[] b = new Point[n];
			int ptr = 0;
			for (int i = 0; i < n; i++) {
				if (!mark[i]) {
					b[ptr++] = a[i];
				}
			}
			a = Arrays.copyOf(b, ptr);
		}

		n = a.length;

		if (n == 0) {
			out.println(-1);
			return;
		}

		BigInteger[] dx = new BigInteger[n];
		BigInteger[] dy = new BigInteger[n];

		for (int i = 0; i < n; i++) {
			int mx = (a[0].x + a[i].x) / 2;
			int my = (a[0].y + a[i].y) / 2;
			dx[i] = b((long)nn * my - sy);
			dy[i] = b(sx - (long)nn * mx);
		}

		BigInteger[] p = new BigInteger[n];

		int ans = 0;

		outer: for (int i = 0; i < n; i++) {
			for (int j = 0; j < i; j++) {
				if (dx[i].multiply(dy[j]).equals(dy[i].multiply(dx[j]))) {
					continue outer;
				}
			}
			for (int j = 0; j < n; j++) {
				p[j] = dx[i].multiply(b(a[j].x)).add(dy[i].multiply(b(a[j].y)));
			}
			Arrays.sort(p);
			BigInteger sum = p[0].add(p[n - 1]);
			for (int p1 = 1, p2 = n - 2; p1 <= p2; p1++, p2--) {
				if (!p[p1].add(p[p2]).equals(sum)) {
					continue outer;
				}
			}
			ans++;
		}
		out.println(ans);
	}

	BigInteger b(long x) {
		return BigInteger.valueOf(x);
	}

	void preCalc() {

	}

	void stress() {

	}

	void test() {

	}

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

	static final Random rng = new Random();

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

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

	BufferedReader br;
	PrintWriter out;
	StringTokenizer st;

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

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

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

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

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