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

public class Main {
    static double max = 0.0;
    public static void main(String[] args) {
        Scanner r = new Scanner(System.in);

        int n = r.nextInt();
        int k = r.nextInt();
        int A = r.nextInt();

        Person[] p = new Person[n];

        for(int i = 0; i < n; i++){
            int l = r.nextInt();
            int prob = r.nextInt();

            p[i] = new Person(l, prob);
        }

        int[] add = new int[n];

        double res = dfs(0, k, p, add, n, A);

        System.out.println(res);

    }
    private static double dfs(int ptr, int k, Person[] p, int[] add, int n, int A) {
        if(k < 0)return 0;

        double res1 = 0;
        for(int m = 0; m < 1<<n; m++){
            double win = 1;
            int cnt = 0;
            for(int i = 0; i < n; i++){
                if((m & (1 << i)) == 0){
                    win *= (100-(p[i].p+add[i]))*1.0/100;
                }else{
                    win *= (add[i]+p[i].p)*1.0/100;
                    cnt++;
                }
            }

            if(cnt > n/2){
                res1 += win;
            }else{
                int B = 0;
                for(int i = 0; i < n; i++){
                    if((m & (1 << i)) == 0){
                        B += p[i].l;
                    }
                }

                win *= A*1.0/(A+B);

                res1 += win;
            }
        }

        double res2 = 0, res3 = 0;

        if(add[ptr]+p[ptr].p < 100){
            add[ptr] += 10;
            res2 = dfs(ptr, k-1, p, add, n, A);
            add[ptr] -= 10;
        }
        if(ptr+1 < n){
            res3 = dfs(ptr+1, k, p, add, n, A);
        }

        return Math.max(res1, Math.max(res2, res3));
    }
}
class Person{
    int l, p;
    public Person(int li, int pi){
        l = li;
        p = pi;
    }
    public String toString(){
        return String.format("[%d, %d]", l, p);
    }
}


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

public class BNew {

    double gAns = 0;

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

    private void solve() throws IOException {
        MyScanner in = new MyScanner(new BufferedReader(new InputStreamReader(System.in)));
        int n = in.nextInt();
        int k = in.nextInt();
        int A = in.nextInt();
        List<Senator> allSenators = new ArrayList<Senator>();
        for (int i = 0; i < n; i++) {
            int level = in.nextInt();
            int loyalty = in.nextInt();
            allSenators.add(new Senator(level, loyalty));
        }
        allSenators = Collections.unmodifiableList(allSenators);

        int npow2 = 1 << n;

        rec(allSenators, 0, k, A);
        for (int okSenatorMask = 0; okSenatorMask < npow2; okSenatorMask++) {
            List<Senator> okSenators = copy(getSenatorsByMask(okSenatorMask, allSenators));
            liftLeastSenators(okSenators, k);
            List<Senator> updatedSenators = new ArrayList<Senator>(okSenators);
            List<Senator> otherSenators = getSenatorsByMask(npow2 - 1 - okSenatorMask, allSenators);
            updatedSenators.addAll(otherSenators);
            check(updatedSenators, A);
        }

        in.close();

        PrintWriter pw = new PrintWriter(System.out);
        System.out.printf("%.6f\n", gAns);
        pw.close();
    }

    private void rec(List<Senator> senators, int senatorId, int k, int A) {
        if (senatorId == senators.size()) {
            check(senators, A);
            return;
        }
        Senator senator = senators.get(senatorId);
        int up = Math.min(k, (100 - senator.loyalty) / 10);
        final int old = senator.loyalty;
        for (int i = 0; i <= up; i++) {
            senator.loyalty = old + i * 10;
            rec(senators, senatorId + 1, k - i, A);
        }
        senator.loyalty = old;
    }

    private void check(List<Senator> senators, double A) {
        double winProp = 0.0;
        for (int mask = 0; mask < 1 << senators.size(); mask++) {
            double caseP = 1.0;
            int okCnt = 0;
            int notOkLevelSum = 0;
            for (int i = 0; i < senators.size(); i++) {
                Senator senator = senators.get(i);
                double senatorLoyalty = senator.loyalty / 100.0;
                boolean ok = (mask & (1 << i)) != 0;
                if (ok) {
                    caseP *= senatorLoyalty;
                    okCnt++;
                } else {
                    caseP *= (1 - senatorLoyalty);
                    notOkLevelSum += senator.level;
                }
            }
            if (okCnt * 2 > senators.size()) {
                winProp += caseP;
            } else {
                double killProp = A / (A + notOkLevelSum);
                winProp += caseP * killProp;
            }
        }
        gAns = Math.max(gAns, winProp);
    }

    List<Senator> copy(List<Senator> senators) {
        List<Senator> copied = new ArrayList<Senator>();
        for (Senator senator : senators) {
            copied.add(new Senator(senator.level, senator.loyalty));
        }
        return copied;
    }

    void liftLeastSenators(List<Senator> senators, int k) {
        if (senators.isEmpty()) {
            return;
        }
        for (int i = 0; i < k; i++) {
            Senator least = senators.get(0);
            for (Senator senator : senators) {
                if (senator.loyalty < least.loyalty) {
                    least = senator;
                }
            }
            if (least.loyalty < 100) {
                least.loyalty += 10;
            }
        }
    }

    List<Senator> getSenatorsByMask(int mask, List<Senator> allSenators) {
        List<Senator> list = new ArrayList<Senator>();
        for (int i = 0; i < allSenators.size(); i++) {
            if ((mask & (1 << i)) != 0) {
                list.add(allSenators.get(i));
            }
        }
        return list;
    }

    static class Senator {
        final int level;
        int loyalty;

        Senator(int level, int loyalty) {
            this.level = level;
            this.loyalty = loyalty;
        }

        @Override
        public String toString() {
            return "{" +
                    "level=" + level +
                    ", loyalty=" + loyalty +
                    '}';
        }
    }

    static class MyScanner {
        final BufferedReader myBr;
        StringTokenizer st = new StringTokenizer("");

        MyScanner(BufferedReader br) {
            myBr = br;
        }

        String nextToken() throws IOException {
            while (!st.hasMoreTokens()) {
                st = new StringTokenizer(myBr.readLine());
            }
            return st.nextToken();
        }

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

        void close() throws IOException {
            myBr.close();
        }
    }
}


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

public class B {

    int n, k, a;
    int[] b, l;

    double best;

    double calc(int i, int r, int c, double p) {
        if (i == n) {
            if (c <= n / 2) {
                p *= 1.0 * a / (a + r);
            }
            return p;
        } else {
            return calc(i + 1, r, c + 1, p * l[i] / 10.0) + calc(i + 1, r + b[i], c, p * (10 - l[i]) / 10.0);
        }
    }

    void go(int i, int k) {
        if (i == n) {
            double p = calc(0, 0, 0, 1.0);
            if (p > best) best = p;
        } else {
            for (int c = 0; c <= k && l[i] + c <= 10; ++c) {
                l[i] += c;
                go(i + 1, k - c);
                l[i] -= c;
            }
        }
    }

    void solve() throws IOException {
        in("__std"); out("__std");

        n = readInt();
        k = readInt();
        a = readInt();
        b = new int[n];
        l = new int[n];
        for (int i = 0; i < n; ++i) {
            b[i] = readInt();
            l[i] = readInt() / 10;
        }

        go(0, k);

        println("%.10f", best);

        exit();
    }

    void in(String name) throws IOException {
        if (name.equals("__std")) {
            in = new BufferedReader(new InputStreamReader(System.in));
        } else {
            in = new BufferedReader(new FileReader(name));
        }
    }

    void out(String name) throws IOException {
        if (name.equals("__std")) {
            out = new PrintWriter(System.out);
        } else {
            out = new PrintWriter(name);
        }
    }

    void exit() {
        out.close();
        System.exit(0);
    }

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

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

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

    String readLine() throws IOException {
        st = null;
        return in.readLine();
    }

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

    boolean eof() throws IOException {
        return !in.ready();
    }

    void print(String format, Object ... args) {
        out.println(new Formatter().format(format, args));
    }

    void println(String format, Object ... args) {
        out.println(new Formatter().format(format, args));
    }

    void print(Object value) {
        out.print(value);
    }

    void println(Object value) {
        out.println(value);
    }

    void println() {
        out.println();
    }

    StringTokenizer st;

    BufferedReader in;
    PrintWriter out;

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


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

public class Main {
	private static StreamTokenizer in;
	private static PrintWriter out;
	static {
		in = new StreamTokenizer(new BufferedReader(new InputStreamReader(
				System.in)));
		out = new PrintWriter(System.out);
	}

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

	private static double nextDouble() throws Exception {
		in.nextToken();
		return in.nval;
	}

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

	public static void main(String[] args) throws Exception {
		int n = nextInt(), k = nextInt(), A = nextInt(), r = n + k - 1;
		int[][] s = new int[n][];
		for (int i = 0; i < n; i++) {
			s[i] = new int[] { nextInt(), nextInt() };
		}
		double max = 0;
		int[] prb = new int[n];
		for (int u = (1 << r); u >= 0; u--) {
			// проверим на n-1 единичек
			int ones = 0;
			for (int i = 0; i < r; i++) {
				if ((u & (1 << i)) != 0) {
					ones++;
				}
			}
			if (ones != n - 1) {
				continue;
			}
			// проверили. расставляем массив
			ones = 0;
			int p = 0;
			for (int i = 0; i < r; i++) {
				if ((u & (1 << i)) == 0) {
					ones++;
				} else {
					prb[p] = ones * 10;
					p++;
					ones = 0;
				}
			}
			prb[p] = ones * 10;
			p++;
			ones = 0;
			double sum = 0;
			for (int i = 0; i < n; i++) {
				if (prb[i] > 100 - s[i][1])
					prb[i] = 100 - s[i][1];
				s[i][1] = prb[i] + s[i][1];
			}
			for (int i = (1 << n) - 1; i >= 0; i--) {
				double prob = 1;
				int lvl = 0;
				int kill = 0;
				for (int j = 0; j < n; j++) {
					if ((i & (1 << j)) != 0) {
						prob *= s[j][1] / 100.0;
						kill--;
					} else {
						lvl += s[j][0];
						prob *= (1 - s[j][1] / 100.0);
						kill++;
					}
				}
				if (kill >= 0) {
					sum += prob * ((double) A / (A + lvl));
				} else {
					sum += prob;
				}
			}
			for (int i = 0; i < n; i++) {
				s[i][1] = -prb[i] + s[i][1];
			}
			max = Math.max(max, sum);
		}
		out.println(max);
		out.flush();
	}
}


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

public class Main{

    public void go(){
        int n=sc.nextInt(), k=sc.nextInt(), A=sc.nextInt();
        ArrayList< ArrayList< Integer > > waysGiveCandies = doit1(n, k, new ArrayList< Integer >());
/*
        System.out.printf("%d\n", waysGiveCandies.size());
        for(ArrayList< Integer > x : waysGiveCandies){
            for(int i : x)
                System.out.printf("%d ", i);
            System.out.printf("\n");
        }
*/
        int[] lvl = new int[n], loyal = new int[n];
        for(int i=0; i<n; ++i){
            lvl[i] = sc.nextInt();
            loyal[i] = sc.nextInt();
        }

        double ret = 0;
        for(ArrayList< Integer > distribution : waysGiveCandies){
            double[] Loyal = new double[n];
            for(int i=0; i<n; ++i) Loyal[i] = min(loyal[i]+10*distribution.get(i), 100)/100.0;
            double pWin = 0;
            for(int i=0; i<1<<n; ++i){
                double pVoteOccurs = 1;
                for(int j=0; j<n; ++j)
                    if((i&(1<<j))!=0) // if winner
                        pVoteOccurs *= Loyal[j];
                    else // if loser
                        pVoteOccurs *= 1-Loyal[j];

                int B = 0;
                for(int j=0; j<n; ++j) if((i&(1<<j))==0)
                    B += lvl[j];
                double pWinFight = (double)A/(A+B);

                // if win vote, don't need to fight
                if(bit_count(i)*2 > n)
                    pWinFight = 1;

                pWin += pVoteOccurs * pWinFight;
            }
            ret = max(ret, pWin);
        }

        System.out.printf("%.9f\n", ret);
    }

    ArrayList< ArrayList< Integer > > doit1(int n, int k, ArrayList< Integer > soFar){
        ArrayList< ArrayList< Integer > > ret = new ArrayList< ArrayList< Integer > >();

        // base case
        if(n==1){
            soFar.add(k);
            ret.add(soFar);
            return ret;
        }

        // general case
        for(int i=0; i<k+1; ++i){
            ArrayList< Integer > tmp = new ArrayList< Integer >(soFar);
            tmp.add(i);
            ret.addAll(doit1(n-1, k-i, tmp));
        }

        return ret;
    }

    // syntax
    // ArrayList<Integer>[] myMat = (ArrayList<Integer>[]) new ArrayList[nB];

    // Pairs
    public class ii implements Comparable< ii >{
        int x, y;
        public ii(){}
        public ii(int xx, int yy){ x=xx; y=yy; }
        public int compareTo(ii p){ return x!=p.x ? x-p.x : y-p.y; }
        public int hashCode(){ return 31*x+y; }
        public boolean equals(Object o){
            if(!(o instanceof ii)) return false;
            ii p = (ii) o;
            return x==p.x && y==p.y;
        }
        public String toString(){ return "("+x+", "+y+")"; }
    }
/*
    public class pair< X extends Comparable< X >,Y extends Comparable< Y > > implements Comparable< pair< X,Y > >{
        X x;
        Y y;
        public pair(){}
        public pair(X xx, Y yy){ x=xx; y=yy; }
        public int compareTo(pair< X,Y > p){ return x.compareTo(p.x)!=0 ? x.compareTo(p.x) : y.compareTo(p.y); }
        public int hashCode(){ return 31*x.hashCode()+y.hashCode(); }
        public boolean equals(Object o){
            if((o.getClass() != this.getClass())) return false;
            pair< X,Y > p = (pair< X,Y >) o;
            return x.equals(p.x) && y.equals(p.y);
        }
        public String toString(){ return "("+x+", "+y+")"; }
    }
*/
    // my stuff
    public static final int INF = 1000*1000*1000+7;
    public static final double EPS = 1e-9;
    public static final double PI = 2*acos(0.0);
    public void rev(Object[] a){ for(int i=0; i<a.length/2; ++i){ Object t=a[i]; a[i]=a[a.length-1-i]; a[a.length-1-i]=t; } }
    public void rev(int[] a){ for(int i=0; i<a.length/2; ++i){ int t=a[i]; a[i]=a[a.length-1-i]; a[a.length-1-i]=t; } }
    public int bit_count(long x){ return x==0 ? 0 : 1+bit_count(x&(x-1)); }
    public int low_bit(int x){ return x&-x; } // 0011 0100 returns 0000 0100
    public int sign(int x){ return x<0 ? -1 : x>0 ? 1 : 0; }
    public int sign(double x){ return x<-EPS ? -1 : x>EPS ? 1 : 0; }
    int[] unpack(ArrayList< Integer > a){
        int[] ret = new int[a.size()];
        for(int i=0; i<a.size(); ++i) ret[i] = a.get(i);
        return ret;
    }

    // generic main stuff
    static myScanner sc;
    static PrintWriter pw;
    static long startTime;
    public static void main(String[] args) throws Exception{
        // sc = new Scanner(System.in);
        sc = (new Main()).new myScanner(new BufferedReader(new InputStreamReader(System.in)));
        pw = new PrintWriter(System.out);
        startTime = System.nanoTime();
        (new Main()).go();
        // errprintln("nanoTime="+(System.nanoTime()-startTime)/1000000/1000.0);
        pw.flush();
        System.exit(0);
    }

    // capable of reading   2.86M 6dp doubles per second
    //                      2.16M 12dp doubles per second
    //                      2.75M int per second
    public class myScanner{
        private BufferedReader f;
        private StringTokenizer st;
        public myScanner(BufferedReader ff){ f=ff; st=new StringTokenizer(""); }
        public int nextInt(){ return Integer.parseInt(nextToken()); }
        public double nextDouble(){ return Double.parseDouble(nextToken()); }
        public String nextLine(){
            st=new StringTokenizer("");
            String ret="";
            try{ ret=f.readLine(); }catch(Exception e){}
            return ret;
        }
        public String nextToken(){
            while(!st.hasMoreTokens()) try{ st=new StringTokenizer(f.readLine()); } catch(Exception e){}
            return st.nextToken();
        }
    }

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

public class ProblemB {
	public static int _gnum;
	public static int _cnum;
	public static int _needs;
	public static int _level;

	public static double _maxans = 0;

	public static double votedfs(int[][] grl, int g, int votes) {
		if (votes >= _needs) {
			return 1.0d;
		}
		if (g >= _gnum) {
			return 0.0d;
		}
		double agrees = (double)grl[g][1] / 100;
		return agrees * votedfs(grl, g+1, votes+1) + (1.0d - agrees) * votedfs(grl, g+1, votes);
	}

	public static double battledfs(int[][] grl, int g, int votes, int levels) {
		if (votes >= _needs) {
			return 0.0d;
		}
		if (g >= _gnum) {
			return (double)_level / (_level + levels);
		}
		double agrees = (double)grl[g][1] / 100;
		return agrees * battledfs(grl, g+1, votes+1, levels) + (1.0d - agrees) * battledfs(grl, g+1, votes, levels + grl[g][0]);
	}

	public static void candydfs(int[][] grl, int g, int n) {
		if (g >= _gnum) {
			double na = votedfs(grl, 0, 0) + battledfs(grl, 0, 0, 0);
			_maxans = Math.max(_maxans, na);
			return;
		}

		int rem = grl[g][1];
		candydfs(grl, g+1, n);
		for (int i = 1 ; i <= n ; i++) {
			if (grl[g][1] < 100) {
				grl[g][1] += 10;
				candydfs(grl, g+1, n-i);
			}
		}
		grl[g][1] = rem;
	}

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line = br.readLine();
        String[] d = line.split(" ");
        int gnum = Integer.valueOf(d[0]);
        int cnum = Integer.valueOf(d[1]);
        int level = Integer.valueOf(d[2]);
        _gnum = gnum;
        _cnum = cnum;
        _needs = (gnum + 1) / 2;
        if (gnum % 2 == 0) {
        	_needs += 1;
        }
        _level = level;

        int[][] grl = new int[gnum][2];
        for (int g = 0 ; g < gnum ; g++) {
        	line = br.readLine();
        	String[] gg = line.split(" ");
        	grl[g][0] = Integer.valueOf(gg[0]);
        	grl[g][1] = Integer.valueOf(gg[1]);
        }

        for (int a = 0 ; a < gnum ; a++) {
            for (int b = 0 ; b < gnum - 1 ; b++) {
            	if (grl[b][1] < grl[b+1][1]) {
            		int tmp = grl[b][0];
            		grl[b][0] = grl[b+1][0];
            		grl[b+1][0] = tmp;
            		tmp = grl[b][1];
            		grl[b][1] = grl[b+1][1];
            		grl[b+1][1] = tmp;
            	}
            }
        }

        int ag = 0;
        int xnum = cnum;
        for (int g = 0 ; g < gnum ; g++) {
        	int needs = (100 - grl[g][1]) / 10;
        	int roy = 0;
        	if (needs <= xnum) {
        		xnum -= needs;
        		roy = 100;
        	} else {
        		roy = grl[g][1] + xnum * 10;
        		xnum = 0;
        	}
        	if (roy >= 100) {
        		ag++;
        	}
        }
        if (ag >= _needs) {
        	System.out.println(1.0);
        	return;
        }

        candydfs(grl, 0, _cnum);

        System.out.println(_maxans);
        br.close();
	}
}


import javax.print.Doc;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.*;

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

    BufferedReader reader;
    StringTokenizer tokenizer;
    PrintWriter writer;
    static String TASK = "";

    void run() throws IOException {
        try {
           // reader = new BufferedReader(new FileReader(TASK + ".in"));
            reader = new BufferedReader(new InputStreamReader(System.in));
            writer = new PrintWriter(System.out);
           // writer = new PrintWriter(TASK + ".out");
            tokenizer = null;
            solve();
            reader.close();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    int b[];
    int l[];
    int add[];
    int n, k, A;

    double ans = 0;
    void solve() throws IOException {
        n = nextInt();
        k = nextInt();
        A = nextInt();
        b = new int[n];
        l = new int[n];
        add = new int[n];
        for (int i = 0; i < n; ++i) {
            b[i] = nextInt();
            l[i] = nextInt();
        }

        brute(0, k);

        writer.printf("%.10f", ans);
    }

    private void brute(int pos, int yet) {
        if (pos == n) {
            /*double prob[][] = new double[n + 1][n + 1];
            prob[0][0] = 1;

            for (int i = 1; i <= n; ++i) {
                for (int sayYes = 1; sayYes <= i; ++sayYes) {
                    prob[i][sayYes] = p[i - 1] * prob[i - 1][sayYes - 1];
                }
                for (int sayYes = 0; sayYes <= i; ++sayYes) {
                    prob[i][sayYes] = (1 - p[i - 1]) * prob[i - 1][sayYes];
                }
            }
            double nowYes = 0;
            for (int i = 0; i <= n; ++i) {
                if (i >= (n + 2) / 2 )
                    nowYes += prob[n][i];
            } */

            double p[] = new double[n];
            for (int i = 0; i < n; ++i) {
                p[i] = (l[i] + add[i]) / 100.0;
            }
            double r = 0;
            for (int i =0; i < (1 << n); ++i) {
                double pr =1 ;
                int sm = 0;
                for (int j =0 ; j < n; ++j) {
                    if ((i & (1 << j)) > 0) {
                        pr *= p[j];
                    }  else {
                        pr *= (1 - p[j]);
                        sm += b[j];
                    }
                }
                int c = Integer.bitCount(i);
                if (c >= (n + 2) / 2) {
                    r += pr;
                } else {
                    r += pr * (1.0 * A / (A + sm));
                }
            }
            ans = Math.max(ans, r);
        } else {
            for (int i = 0; i <= yet; ++i) {
                if (l[pos] + 10 * i > 100) continue;
                add[pos] = 10 * i;
                brute(pos + 1, yet - i);
            }
        }
    }

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

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

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

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

    BigInteger nextBigInteger() throws IOException {
        return new BigInteger(nextToken());
    }
}


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

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

    static class TaskB {
        double ans = 0;
        int[] candy;
        int[] b;
        int[] l;
        int[] curLoyal;
        int n;
        int k;
        int A;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            n = in.nextInt();
            k = in.nextInt();
            A = in.nextInt();
            b = new int[n];
            l = new int[n];
            for (int i = 0; i < n; i++) {
                b[i] = in.nextInt();
                l[i] = in.nextInt();
            }
            candy = new int[n];
            curLoyal = new int[n];
            comb(0, k);
            out.println(ans);
        }

        void comb(int ind, int unusedCandy) {
            if (ind == n) {
                for (int i = 0; i < n; i++) {
                    curLoyal[i] = Math.min(candy[i] * 10 + l[i], 100);
                }
                calc();
            } else {
                for (int i = 0; i <= unusedCandy; i++) {
                    candy[ind] = i;
                    comb(ind + 1, unusedCandy - i);
                }
            }
        }

        void calc() {
            double res = 0;
            int allBits = (1 << n) - 1;
            for (int vote = 0; vote <= allBits; vote++) {
                double curProb = 1;
                int sumPower = A;
                int enemyCnt = 0;
                for (int voteInd = 0; voteInd < n; voteInd++) {
                    if ((vote & (1 << voteInd)) == 0) {
                        curProb *= 100 - curLoyal[voteInd];
                        sumPower += b[voteInd];
                        enemyCnt++;
                    } else {
                        curProb *= curLoyal[voteInd];
                    }
                    curProb /= 100;
                }
                if (2 * enemyCnt >= n) {
                    curProb *= A;
                    curProb /= sumPower;
                }
                res += curProb;
            }
            ans = Math.max(ans, res);
        }

    }

    static class InputReader {
        private BufferedReader reader;
        private StringTokenizer stt;

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

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

        public String next() {
            while (stt == null || !stt.hasMoreTokens()) {
                stt = new StringTokenizer(nextLine());
            }
            return stt.nextToken();
        }

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

    }
}


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

public class Main {

    StreamTokenizer in;
    PrintWriter out;

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

    public void run() throws Exception {
        Locale.setDefault(Locale.US);
        in = new StreamTokenizer (new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(new OutputStreamWriter(System.out));
        solve();
        out.flush();
    }

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

    public String next() throws Exception {
        in.nextToken();
        return in.sval;
    }

    class Senator {
        int b;
        int l;

        public Senator (int b,int l) {
            this.b=b;
            this.l=l;
        }

    }

    int n,k,A;
    double max=Integer.MIN_VALUE;
    Senator[] a;

    public void check (int step,int candy) {
        if (step==n)
        {
            double tmp = 0.0;
            for (int mask=0; mask<(1<<n);mask++)
            {
                double P = 1.0;
                int q = 0;
                for (int i=0; i<n;i++)
                {
                    if ((mask>>i&1)!=0)
                    {
                        P*=a[i].l/100.;
                    } else
                    {
                        P*=1.0-a[i].l/100.;
                        q+=a[i].b;
                    }
                }
                if (Integer.bitCount(mask)>n/2)
                {
                    tmp+=P;
                } else
                {
                    tmp+=P*A/(A+q);
                }
                max=Math.max(tmp,max);
            }
        } else
        {
            for (int i=0;i<=Math.min(k,(100-a[step].l)/10);i++)
            {
                a[step].l+=10*i;
                check(step+1,k-i);
                a[step].l-=10*i;
            }
        }
    }

    public void solve() throws Exception {
        n=nextInt();
        k=nextInt();
        A=nextInt();
        a = new Senator [n];
        for (int i=0; i<n;i++) {
            Senator q = new Senator(nextInt(),nextInt());
            a[i]=q;
        }
        double ans=0;
        for(int mask=0;mask<1<<(n+k-1);mask++)
        {
            if(Integer.bitCount(mask)!=k) continue;
            int[] b = new int[n];
            int x = mask;
            for(int i=0;i<n;i++)
            {
                b[i] = a[i].l;
                while(x%2==1)
                {
                    b[i]+=10;
                    x/=2;
                }
                b[i]=Math.min(b[i],100);
                x/=2;
            }
            double tmp=0;
            for(int w=0; w<(1<<n);w++)
            {
                double p = 1.;
                double B = 0;
                for(int i = 0; i < n; i++)
                    if((w >> i & 1) != 0) p *= b[i] / 100.;
                    else
                    {
                        p *= 1- b[i]/100.;
                        B += a[i].b;
                    }
                if(Integer.bitCount(w)> n/2) tmp += p;
                else tmp += p * (A / (A + B));
            }
            ans = Math.max(ans, tmp);
        }
        out.printf("%.10f\n", ans);
    }
}


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

public class TemnayaAssambleya implements Runnable {
	public static void main(String[] args) {
		new Thread(new TemnayaAssambleya()).run();
	}

	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	StringTokenizer in;
	PrintWriter out = new PrintWriter(System.out);

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

		return in.nextToken();
	}

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

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

	int[] l;
	int[] ln;
	int[] pw;
	int[] p;
	int A;
	double max = 0;

	public void gen(int n, int k) {
		if (n == 0) {
			n = p.length;
			p[0] = k;
			for (int i = 0; i < n; i++) {
				ln[i] = l[i] + p[i] * 10;
				if (ln[i] > 100)
					ln[i] = 100;
			}

			double ans = 0;
			for (int mask = 0; mask < 1 << n; mask++) {
				int z = 0;
				double pos = 1;
				int power = 0;
				for (int i = 0; i < n; i++) {
					if ((mask & (1 << i)) > 0) {
						z++;
						pos *= ln[i] * 1. / 100;
					} else {
						pos *= (100 - ln[i]) * 1. / 100;
						power += pw[i];
					}
				}

				if (z > n / 2) {
					ans += pos;
				} else {
					ans += pos * A / (A + power);
				}
			}

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

		for (int i = 0; i <= Math.min(k, 10 - l[n] / 10); i++) {
			p[n] = i;
			gen(n - 1, k - i);
		}
	}

	public void solve() throws IOException {
		int n = nextInt();
		int k = nextInt();
		A = nextInt();

		p = new int[n];
		pw = new int[n];
		l = new int[n];
		ln = new int[n];

		for (int i = 0; i < n; i++) {
			pw[i] = nextInt();
			l[i] = nextInt();
		}

		gen(n - 1, k);
		out.println(max);
	}

	public void run() {
		try {
			solve();
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	}
}


import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;

public class B implements Runnable {

    int a;
    int[] b;
    int[] l;

    public void solve() throws IOException {
        int n = in.nextInt();
        int k = in.nextInt();
        a = in.nextInt();
        b = new int[n];
        l = new int[n];
        for ( int i = 0; i < n; i ++ ) {
            b[i] = in.nextInt();
            l[i] = in.nextInt();
        }
        out.println( best( 0, k ));
    }

    double best( int cur, int left ) {
        double r = 0.0;
        if ( cur < l.length ) {
            for ( int i = 0; i <= left && l[cur] + 10 * i <= 100; i ++ ) {
                l[cur] += i * 10;
                r = Math.max( r, best( cur + 1, left - i ) );
                l[cur] -= i * 10;
            }
        } else {
            for ( int m = 0; m < ( 1 << l.length ); m ++ ) {
                int sum = 0;
                double p = 1.0;
                int pro = 0;
                for ( int i = 0; i < l.length; i ++ ) {
                    if ( ( m & ( 1 << i ) ) == 0 ) {
                        p *= 1.0 - l[i] * 0.01;
                        sum += b[i];
                    } else {
                        p *= l[i] * 0.01;
                        pro ++;
                    }
                }
                if ( pro * 2 > l.length ) {
                    r += p;
                } else {
                    r += ( p * a ) / ( a + sum );
                }
            }
        }
        return r;
    }

    public Scanner in;

    public PrintWriter out;

    B() throws IOException {
        in = new Scanner(System.in);
        // in = new StreamTokenizer( new InputStreamReader( System.in ) );
        out = new PrintWriter(System.out);
    }

//    int nextInt() throws IOException {
//        in.nextToken();
//        return ( int ) in.nval;
//    }

    void check(boolean f, String msg) {
        if (!f) {
            out.close();
            throw new RuntimeException(msg);
        }
    }

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

    public void run() {
        try {
            solve();
            close();
        } catch (Exception e) {
            e.printStackTrace(out);
            out.flush();
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) throws IOException {
        new Thread(new B()).start();
    }
}


/**
 * Created by IntelliJ IDEA.
 * User: Taras_Brzezinsky
 * Date: 8/13/11
 * Time: 6:10 PM
 * To change this template use File | Settings | File Templates.
 */

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

public class DarkAssembly extends Thread {

    public DarkAssembly() {
        this.input = new BufferedReader(new InputStreamReader(System.in));
        this.output = new PrintWriter(System.out);
        this.setPriority(Thread.MAX_PRIORITY);
    }

    static class Senator {
        int loyalty;
        int level;

        public Senator(int level, int loyalty) {
            this.level = level;
            this.loyalty = loyalty;
        }
    }

    private static double doIt(Senator[] senators, int A) {
        double probability = .0;
        for (int mask = 0; mask < (1 << senators.length); ++mask) {
            int sum = A;
            double current = 1.0;
            for (int i = 0; i < senators.length; ++i) {
                if ((mask & (1 << i)) != 0) {
                    current *= .01 * senators[i].loyalty;
                } else {
                    current *= .01 * (100 - senators[i].loyalty);
                    sum += senators[i].level;
                }
            }
            if (Integer.bitCount(mask) > senators.length / 2) {
                probability += current;
            } else {
                probability += current * (double) A / sum;
            }
        }
        return probability;
    }

    private static double go(Senator[] senators, int candies, int A, int current) {
        if (current == senators.length) {
            return doIt(senators, A);
        } else {
            double result = go(senators, candies, A, current + 1);
            if (candies > 0 && senators[current].loyalty < 100) {
                senators[current].loyalty += 10;
                result = Math.max(result, go(senators, candies - 1, A, current));
                senators[current].loyalty -= 10;
            }
            return result;
        }
    }

    private void solve() throws Throwable {
        int n = nextInt();
        int k = nextInt();
        int A = nextInt();
        Senator[] senators = new Senator[n];
        for (int i = 0; i < n; ++i) {
            senators[i] = new Senator(nextInt(), nextInt());
        }
        output.printf("%.10f", go(senators, k, A, 0));
    }

    public void run() {
        try {
            solve();
        } catch (Throwable e) {
            System.err.println(e.getMessage());
            e.printStackTrace();
        } finally {
            output.flush();
            output.close();
        }

    }

    public static void main(String[] args) {
        new DarkAssembly().start();
    }

    private String nextToken() throws IOException {
        while (tokens == null || !tokens.hasMoreTokens()) {
            tokens = new StringTokenizer(input.readLine());
        }
        return tokens.nextToken();
    }

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

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

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

    private BufferedReader input;
    private PrintWriter output;
    private StringTokenizer tokens = null;
}


import java.util.Scanner;

public class B {
    static int n;
    static double A;
    static int[] L;
    static int[] B;
    static double max = 0;

    public static void rec(int index, int k) {
        if (k < 0)
            return;
        if (index == n) {
            double prob = 0;
            for (int i = 0; i < (1 << n); i++) {
                double b = 0;
                double temp = 1.0;
                for (int j = 0; j < n; j++) {
                    if (L[j] > 100)
                        return;
                    if ((i & (1 << j)) == 0) {
                        b += B[j];
                        temp *= (100 - L[j]) / 100.0;
                    } else
                        temp *= L[j] / 100.0;
                }
                if (Integer.bitCount(i) * 2 <= n)
                    temp *= A / (A + b);
                prob += temp;

            }
            max = Math.max(max, prob);
            return;
        }
        L[index] += 10;
        rec(index, k - 1);
        L[index] -= 10;
        rec(index + 1, k);
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        n = in.nextInt();
        int k = in.nextInt();
        A = in.nextDouble();
        B = new int[n];
        L = new int[n];
        for (int i = 0; i < n; i++) {
            B[i] = in.nextInt();
            L[i] = in.nextInt();
        }
        rec(0, k);
        System.out.println(max);
    }
}


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.Map.Entry;

public class Solution implements Runnable {

	public static void main(String[] args) {
		(new Thread(new Solution())).start();
	}

	BufferedReader in;
	PrintWriter out;
	StringTokenizer st;

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

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

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

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

	int n;
	int[] b, l;
	double ans;
	int[] sw;
	int a;

	void sol() {
		for (int i = 0; i < n; i++) l[i] += sw[i] * 10;
		double yes = 0;
		for (int q = 0; q < (1 << n); q++) {
			double p = 1;
			int bb = 0;
			int cnt = 0;
			for (int i = 0; i < n; i++) {
				if ((q & (1 << i)) == 0) {
					p *= (1.0 - (double)l[i] / 100);
					bb += b[i];
				} else {
					p *= 1.0 * (double)l[i] / 100;
					cnt++;
				}
			}
			if (cnt > n / 2) {
				yes += p;
			} else {
				yes += p * (double)a / (double)(a + bb);
			}
		}
		if (ans < yes) ans = yes;
		for (int i = 0; i < n; i++) l[i] -= sw[i] * 10;
	}

	void rek(int i, int k) {
		if (i == n) sol(); else {
			for (int q = 0; q <= k && l[i] + q * 10 <= 100; q++) {
				sw[i] = q;
				rek(i + 1, k - q);
			}
		}
	}

	void solve() throws Exception {
		n = nextInt();
		int k = nextInt();
		a = nextInt();
		b = new int[n];
		l = new int[n];
		sw = new int[n];
		for (int i = 0; i < n; i++) {
			b[i] = nextInt();
			l[i] = nextInt();
		}
		rek(0, k);
		out.printf("%.10f", ans);
	}

	public void run() {
		Locale.setDefault(Locale.UK);
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
//			in = new BufferedReader(new FileReader("knights.in"));
//			out = new PrintWriter("knights.out");
			solve();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		} finally {
			out.flush();
		}
	}

}


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

public class B {

    BufferedReader br;
    PrintWriter out;
    StringTokenizer st;
    boolean eof;

    int[] level;
    int[] loyal;
    double ans;
    int n, k, plLev, needVotes;

    double check() {

        //System.err.println(Arrays.toString(loyal));
        double res = 0;
        for (int mask = 0; mask < (1 << n); mask++) {
            double prob = 1;
            int vote = 0;
            int kill = 0;
            for (int i = 0; i < n; i++)
                if (((mask >> i) & 1) == 1) {
                    prob *= loyal[i] / 100.0;
                    vote++;
                }
                else {
                    prob *= 1 - loyal[i] / 100.0;
                    kill += level[i];
                }
            if (vote >= needVotes)
                res += prob;
            else
                res += prob * plLev / (kill + plLev);
        }

        return res;
    }

    void go(int ind, int candy) {
        if (ind == n) {
            ans = Math.max(ans, check());
            return;
        }

        for (int i = 0; i <= candy; i++) {
            loyal[ind] += 10 * i;
            if (loyal[ind] > 100) {
                loyal[ind] -= 10 * i;
                break;
            }
            go(ind + 1, candy - i);
            loyal[ind] -= 10 * i;
        }

    }

    void solve() throws IOException {

        n = nextInt();
        k = nextInt();
        plLev = nextInt();
        needVotes = n / 2 + 1;
        ans = 0;

        level = new int[n];
        loyal = new int[n];

        for (int i = 0; i < n; i++) {
            level[i] = nextInt();
            loyal[i] = nextInt();
        }

        go(0, k);

        out.printf("%.12f", ans);
    }

    void inp() throws IOException {
        Locale.setDefault(Locale.US);
        br = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(System.out);
        solve();
        out.close();
    }

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

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

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

    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.util.*;
import java.io.*;
import static java.lang.Math.*;

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

    double ans = 0;
    int n, candy, A, half;

    void run() throws Exception{
        Scanner sc = new Scanner(System.in);
        //BufferedReader sc = new BufferedReader(new InputStreamReader(System.in));
        // only sc.readLine() is available
        n = sc.nextInt();
        candy = sc.nextInt();
        A = sc.nextInt();
        half = n/2;
        //int[] level = new int[n];
        //int[] loyal = new int[n];
        S[] ss = new S[n];
        for(int i = 0; i < n; i++){
            ss[i] = new S(sc.nextInt(), sc.nextInt());
        }
        Arrays.sort(ss);
        int need = 0;
        for(int i = n-1; i >= n-half-1; i--)
            need += (100-ss[i].loyal)/10;
        if(need <= candy){
            System.out.println(1.0);
            return;
        }
        tra(ss, 0, candy);
        /*
        while(candy > 0){
            int ind = 0;
            for(int i = 1; i < n; i++)
                if(ss[i].loyal < 100 && ss[ind].level < ss[i].level)
                    ind = i;
            ss[ind].loyal += 10;
            ss[ind].loyal = min(100, ss[ind].loyal);
            candy--;
        }
        */
        System.out.printf("%.10f\n", ans);
    }

    void tra(S[] ss, int pos, int rest){
        if(pos == n){
            double sum = 0;
            int lim = 1<<n;
            for(int m = 0; m < lim; m++){
                int app = Integer.bitCount(m);
                double p = 1;
                int B = 0;
                for(int i = 0; i < n; i++){
                    if(((m>>i) & 1) == 1){
                        p = p * ss[i].loyal / 100;
                    }else{
                        p = p * (100 - ss[i].loyal) / 100;
                        B += ss[i].level;
                    }
                }
                if(app > half)sum += p;
                else{
                    sum += p * A / (A+B);
                }
            }
            ans = max(ans, sum);
            return;
        }
        for(int i = 0; i <= rest; i++){
            int old = ss[pos].loyal;
            int nl = ss[pos].loyal + i * 10;
            if(nl > 100)break;
            ss[pos].loyal = nl;
            tra(ss, pos+1, rest-i);
            ss[pos].loyal = old;
        }
    }
}

class S implements Comparable<S>{
    int level, loyal;
    S(int a, int b){
        level = a;
        loyal = b;
    }
    public int compareTo(S s){
        return this.loyal - s.loyal;
    }
}


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

public class Main implements Runnable {
	int[] conf, L, B;
	int n, k, A, sz;
	double[] kill;
	double best = 0;

	double solv() {
		double res = 0;
		double[] a = new double[n];
		for (int i=0; i<n; i++)
			a[i] = Math.min(100, L[i]+10*conf[i])/100.0;
		double[] dp1 = new double[sz];
		double[] dp2 = new double[sz];
		dp1[0] = 1;
		for (int i=0; i<n; i++) {
			for (int msk=0; msk<sz; msk++) {
				dp2[msk] += dp1[msk]*a[i];
				dp2[msk|(1<<i)] += dp1[msk]*(1-a[i]);
			}
			for (int msk=0; msk<sz; msk++) {
				dp1[msk] = dp2[msk]; dp2[msk] = 0;
			}
		}
		/*for (int msk=0; msk<sz; msk++) {
			double p = 1;
			int cnt = 0;
			for (int i=0; i<n; i++)
				if ((msk&(1<<i))>0) {
					p *= (100-a[i])/100.0;
				} else {
					p *= a[i]/100.0;
					cnt++;
				}
			if (cnt>n/2) res += p; else res += p*kill[msk];
		}
		res /= sz;*/

		for (int msk=0; msk<sz; msk++){
			if (n-Integer.bitCount(msk) > n/2) res += dp1[msk]; else res += dp1[msk]*kill[msk];
		}

		return res;

	}
	void gen(int n, int k) {
		if (n==0) {
			conf[0] = k;
			//conf[0] = 2; conf[1] = 1; conf[2] = 3;
			double x = solv();
			if (x>best) best = x;
			return;

		}
		for (int i=0; i<=k; i++) {
			conf[n] = i;
			gen(n-1, k-i);
		}
		conf[n] = 0;
	}
	void solve() throws IOException {
		n = nextInt();
		k = nextInt();
		A = nextInt();
		B = new int[n];
		L = new int[n];
		for (int i=0; i<n; i++) {
			B[i] = nextInt();
			L[i] = nextInt();
		}
		sz = 1<<n;
		conf = new int[n];
		kill = new double[sz];
		for (int msk=0; msk<sz; msk++) {
			int sum = 0;
			for (int i=0; i<n; i++)
				if ((msk&(1<<i))>0) {
					sum += B[i];
				}
			kill[msk] = A*1./(A+sum);
		}
		gen(n-1, k);
		out.printf(Locale.US, "%1.9f", best);

	}

	BufferedReader br;
	StringTokenizer st;
	PrintWriter out;

	public void run() {
		try {
			br = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
			// br = new BufferedReader(new FileReader("input.txt"));
			// out = new PrintWriter("output.txt");
			solve();
			br.close();
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(123);
		}
	}

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

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

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

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

	public static void main(String[] args) {
		new Thread(new Main()).start();
	}
}


//package contest10D;
import java.math.*;
import java.util.*;
import static java.math.BigInteger.*;
import static java.lang.Math.*;
import static java.util.Arrays.*;
import static java.util.Collections.*;

public class Main {
	static void debug(Object... os) {
		System.err.println(deepToString(os));
	}

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

	void run() {
		Scanner sc = new Scanner(System.in);
		int n=sc.nextInt(),m=sc.nextInt();
		boolean[][] bs=new boolean[n][n];
		for (int i = 0; i < m; i++) {
			int s=sc.nextInt()-1,t=sc.nextInt()-1;
			bs[s][t] = bs[t][s] = true;
		}
		long res = 0;
		for(int i=0;i<n;i++){
			res += calc(bs,n-1-i);
		}
		System.out.println(res/2);
	}
	long calc(boolean[][] bs,int n){//start is n.
		long[][] dp=new long[1<<n][n]; // set,last -> number of path n -> last.
		for(int i=0;i<n;i++){
			if(bs[i][n])
				dp[1<<i][i] ++;
		}
		for(int i=1;i<1<<n;i++){
			for(int j=0;j<n;j++)if(((i>>j)&1)==1)
				for(int k=0;k<n;k++)if(((i>>k)&1)==0 && bs[j][k]){//add
					dp[i|(1<<k)][k] += dp[i][j];
				}
		}
		long res=0;
		for(int i=0;i<1<<n;i++)for(int j=0;j<n;j++)if(Integer.bitCount(i)>=2&&bs[j][n])res+=dp[i][j];
		return res;
	}

}


	import java.awt.List;
	import java.io.IOException;
	import java.io.InputStream;
	import java.io.OutputStream;
	import java.io.PrintWriter;
	import java.math.BigDecimal;
	import java.math.BigInteger;
	import java.text.DecimalFormat;
	import java.util.ArrayList;
	import java.util.Arrays;
	import java.util.HashMap;
	import java.util.InputMismatchException;
	import java.util.Locale;
	import java.util.TimeZone;

	public class Cycle {

		public static void main(String[] args) {
			Locale.setDefault(Locale.US);
			InputStream inputstream = System.in;
			OutputStream outputstream = System.out;
			FastReader in = new FastReader(inputstream);
			PrintWriter out = new PrintWriter(outputstream);
			TaskA solver = new TaskA();
			// int testcase = in.ni();
			for (int i = 0; i < 1; i++)
				solver.solve(i, in, out);
			out.close();

		}

	}

	class TaskA {

		public void solve(int testnumber, FastReader in, PrintWriter out) {

			int n = in.ni();
			int m = in.ni();

			boolean graph[][] = new boolean[n][n];

			for (int i = 0; i < m; i++) {
				int a = in.ni() - 1;
				int b = in.ni() - 1;

				graph[a][b] = true;
				graph[b][a] = true;
			}

			/*
			 * dp[mask][i] be the number of Hamiltonian walks over the subset mask,
			 * starting at the vertex first(mask) and ending at the vertex i
			 */

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

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

			long answer = 0;
			for (int mask = 1; mask < (1 << n); mask++) {
				int start = Integer.numberOfTrailingZeros(mask);

				for (int i = 0; i < n; i++) {
					if ((mask & (1 << i)) == 0) {
						continue;
					}

					for (int j = start + 1; j < n; j++) {
						if (graph[i][j] && (mask & (1 << j)) == 0) {
							dp[mask + (1 << j)][j] += dp[mask][i];
						}

					}
					if (graph[i][start]) {
						answer += dp[mask][i];
					}
				}

			}

			out.println((answer - m) / 2);
		}
	}

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

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

		public FastReader() {

		}

		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 ni() {
			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 ns() {
			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 isWhitespace(c);
		}

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

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

		public String next() {
			return ns();
		}

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

	}


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

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author Darshandarji
 */
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);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();
            boolean[][] g = new boolean[n][n];
            for (int i = 0; i < m; ++i) {
                int a = in.nextInt() - 1;
                int b = in.nextInt() - 1;
                g[a][b] = true;
                g[b][a] = true;
            }
        /*for (int i = 0; i < n; ++i)
            for (int j = 0; j < n; ++j)
                g[i][j] = true;*/
            long[] am = new long[n + 1];
            long[][] ways = new long[1 << n][n];
            for (int start = 0; start < n; ++start) {
                for (int mask = 0; mask < (1 << (n - start)); ++mask)
                    for (int last = start; last < n; ++last) {
                        ways[mask][last - start] = 0;
                    }
                ways[1][0] = 1;
                for (int mask = 0; mask < (1 << (n - start)); ++mask) {
                    int cnt = 0;
                    int tmp = mask;
                    while (tmp > 0) {
                        ++cnt;
                        tmp = tmp & (tmp - 1);
                    }
                    for (int last = start; last < n; ++last)
                        if (ways[mask][last - start] > 0) {
                            long amm = ways[mask][last - start];
                            for (int i = start; i < n; ++i)
                                if ((mask & (1 << (i - start))) == 0 && g[last][i]) {
                                    ways[mask | (1 << (i - start))][i - start] += amm;
                                }
                            if (g[last][start])
                                am[cnt] += ways[mask][last - start];
                        }
                }
            }
            long res = 0;
            for (int cnt = 3; cnt <= n; ++cnt) {
                if (am[cnt] % (2) != 0)
                    throw new RuntimeException();
                res += am[cnt] / (2);
            }
            out.println(res);
        }

    }

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

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

        public int read() {
            if (numChars == -1)
                throw new InputMismatchException();

            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }

                if (numChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public int nextInt() {
            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 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.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;

/**
 * Created by Tejas on 18-10-2018.
 */
public class Main {

    static HashSet<Integer> adjList[];
    public static void main(String[]args)throws IOException{
        BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(System.in));
        StringBuilder stringBuilder=new StringBuilder();

        String temp[]=bufferedReader.readLine().split(" ");
        int V=Integer.parseInt(temp[0]);
        int E=Integer.parseInt(temp[1]);
        adjList=new HashSet[V];
        for(int i=0;i<V;i++)
            adjList[i]=new HashSet<>();
        for(int i=0;i<E;i++){
            temp=bufferedReader.readLine().split(" ");
            int x=Integer.parseInt(temp[0])-1;
            int y=Integer.parseInt(temp[1])-1;
            adjList[y].add(x);
            adjList[x].add(y);
        }
        stringBuilder.append(solve(V)+"\n");
        System.out.println(stringBuilder);
    }

    private static long solve(int V) {

        long dp[][]=new long[(1<<V)][V];
        long count=0;
        for(int i=0;i<V;i++)
            dp[(1<<i)][i]=1;
        for(int mask=1;mask<(1<<V);mask++){
            // HW starting at pos first and ending at j.
            int first = Integer.numberOfTrailingZeros(mask);
            for(int i=0;i<V;i++){
                if((mask&(1<<i))==0 || first==i) continue;
                for (int j = 0; j < V; j++)
                    if (adjList[i].contains(j) && (mask & (1<<j))!=0)
                        dp[mask][i] += dp[mask ^ (1 << i)][j];
                //Calculating simple cycles
                if (Integer.bitCount(mask)>=3)
                    if(adjList[first].contains(i))
                        count+=dp[mask][i];
            }
        }
        return count/2;
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.util.ArrayList;
import java.io.InputStream;
/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author Alex
 */
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);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }
    static class TaskD {
        int n;
        ArrayList<Integer>[] adj;
        long[] mem;
        int start;
        long cycles(int cur, int visited) {
            if (cur == start && visited > 0) {
                return Integer.bitCount(visited) >= 3 ? 1 : 0;
            }
            int index = visited * n + cur;
            if (mem[index] != -1) return mem[index];
            long res = 0;
            int newvisited = visited | (1 << cur);
            for (int nxt : adj[cur]) {
                if (nxt >= start && (nxt == start || ((visited >> nxt) & 1) == 0)) {
                    res += cycles(nxt, newvisited);
                }
            }
            return mem[index] = res;
        }
        public void solve(int testNumber, InputReader in, OutputWriter out) {
            n = in.readInt();
            int m = in.readInt();
            adj = new ArrayList[n];
            mem = new long[n * (1 << n)];
            for (int i = 0; i < adj.length; i++) adj[i] = new ArrayList<>();
            for (int i = 0; i < m; i++) {
                int a = in.readInt() - 1, b = in.readInt() - 1;
                adj[a].add(b);
                adj[b].add(a);
            }
            long res = 0;
            for (int start = 0; start < n; start++) {
                Arrays.fill(mem, -1);
                this.start = start;
                res += cycles(start, 0) / 2;
            }
            out.printLine(res);
        }
    }
    static class OutputWriter {
        private final PrintWriter writer;
        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }
        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }
        public void close() {
            writer.close();
        }
        public void printLine(long i) {
            writer.println(i);
        }
    }
    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;
        public InputReader(InputStream stream) {
            this.stream = stream;
        }
        public int read() {
            if (numChars == -1)
                throw new InputMismatchException();
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }
        public 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 boolean isSpaceChar(int c) {
            if (filter != null)
                return filter.isSpaceChar(c);
            return isWhitespace(c);
        }
        public static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }
        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);
        }
    }
}


import java.util.Scanner;

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

	boolean[][] graph;
	public void run() {

		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();

		graph = new boolean[n][n];
		for (int i = 0; i < m; i++) {
			int a = sc.nextInt() - 1;
			int b = sc.nextInt() - 1;
			graph[a][b] = true;
			graph[b][a] = true;
		}

		long res = 0;
		for (int i = 3; i <= n; i++) {
			res += solve(i);
		}
		System.out.println(res);

	}

	long solve(int n) {
		// [0, n)の頂点だけで、n-1 スタートだけ考える
		long[][] dp = new long[1 << n][n];
		dp[1 << (n-1)][n-1] = 1;

		for (int i = 0; i < (1 << n); ++i) {
			for (int l = 0; l < n; ++l) if (dp[i][l] > 0) {
				for (int x = 0; x < n - 1; ++x) if (graph[l][x] && (i >> x & 1) == 0) {
					dp[i | (1 << x)][x] += dp[i][l];
				}
			}
		}

		long res = 0;
		for (int i = 0; i < (1 << n); ++i) if (Integer.bitCount(i) >= 3) {
			for (int l = 0; l < n; ++l) {
				if (graph[l][n-1]) res += dp[i][l];
			}
		}
		return res / 2; // n-1 を含むサイクルを右回りと左回り数えてしまったので２で割る
	}

}


import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();

        boolean[][] graph = new boolean[n][n];

        for(int i = 0; i < m; i++) {
            int from = in.nextInt() - 1;
            int to = in.nextInt() - 1;
            graph[from][to] = true;
            graph[to][from] = true;
        }

        int max = 1 << n;
        long[][] dp = new long[max][n];
        for(int mask = 1; mask < max; mask++) {
            for(int i = 0; i < n; i++) {
                int countMask = Integer.bitCount(mask);
                boolean existSubSeti = (mask & (1 << i)) > 0;
                if(countMask == 1 && existSubSeti) {
                    dp[mask][i] = 1;
                }
                else if(countMask > 1 && existSubSeti) {
                    int mask1 = mask ^ (1 << i);
                    for(int j = 0; j < n; j++) {
                        if(((mask1 & (1 << j)) > 0) && graph[j][i] && i != firstMask(mask, n)) {
                            dp[mask][i] += dp[mask1][j];
                        }
                    }
                }
            }
        }

        long counter = 0;
        for(int mask = 1; mask < max; mask++) {
            for(int i = 0; i < n; i++) {
                if(Integer.bitCount(mask) >= 3 && graph[firstMask(mask, n)][i]) {
                    counter += dp[mask][i];
                }
            }

        }
        System.out.println(counter / 2);
        in.close();
    }

    public static int firstMask(int mask, int n) {
        for(int i = 0; i < n; i++) {
            if((mask & (1 << i)) > 0) return i;
        }
        return -1;

    }
}


import java.util.*;

public class Solution {
    public void doMain() throws Exception {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), m = sc.nextInt();
        boolean[][] adj = new boolean[n][n];
        for (int i=0; i<m; i++) {
            int a = sc.nextInt()-1, b = sc.nextInt()-1;
            adj[a][b] = adj[b][a] = true;
        }

        long res = 0;

        for (int st=0; st+1<n; st++) {
            //System.out.println("st="+st);
            long[][] numWays = new long[1<<(n-st-1)][n-st-1];
            for (int i=st+1; i<n; i++)
                if (adj[st][i]) numWays[1<<(i-st-1)][i-st-1] = 1;

            for (int mask=1; mask < (1<<(n-st-1)); mask++) {
                boolean simple = ((mask & (mask-1)) == 0);
                for (int last=0; last<n-st-1; last++) if (numWays[mask][last]!=0) {
                    if (adj[last+st+1][st] && !simple) res += numWays[mask][last];
                    for (int next=0; next<n-st-1; next++)
                        if (adj[last+st+1][next+st+1] && (mask & (1<<next)) == 0)
                            numWays[mask | (1<<next)][next] += numWays[mask][last];
                }
            }
        }

        System.out.println(res/2);
    }
    public static void main(String[] args) throws Exception {
        (new Solution()).doMain();
    }
}


import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();

        boolean[][] graph = new boolean[n][n];

        for(int i = 0; i < m; i++) {
            int from = in.nextInt() - 1;
            int to = in.nextInt() - 1;
            graph[from][to] = true;
            graph[to][from] = true;
        }

        int max = 1 << n;
        long[][] dp = new long[max][n];
        for(int mask = 1; mask < max; mask++) {
            for(int i = 0; i < n; i++) {
                int countMask = Integer.bitCount(mask);
                boolean existSubSeti = (mask & (1 << i)) > 0;
                if(countMask == 1 && existSubSeti) {
                    dp[mask][i] = 1;
                }
                else if(countMask > 1 && existSubSeti) {
                    int mask1 = mask ^ (1 << i);
                    for(int j = 0; j < n; j++) {
                        if(graph[j][i] && i != firstMask(mask, n)) {
                            dp[mask][i] += dp[mask1][j];
                        }
                    }
                }
            }
        }

        long counter = 0;
        for(int mask = 1; mask < max; mask++) {
            for(int i = 0; i < n; i++) {
                if(Integer.bitCount(mask) >= 3 && graph[firstMask(mask, n)][i]) {
                    counter += dp[mask][i];
                }
            }

        }
        System.out.println(counter / 2);
        in.close();
    }

    public static int firstMask(int mask, int n) {
        for(int i = 0; i < n; i++) {
            if((mask & (1 << i)) > 0) return i;
        }
        return -1;

    }
}


import java.util.Arrays;

/**
 * Created by IntelliJ IDEA.
 * User: piyushd
 * Date: 12/31/10
 * Time: 1:30 PM
 * To change this template use File | Settings | File Templates.
 */
public class SimpleCycle {

	int first(int x){
		return x - (x & (x - 1));
	}

    void run(){
		int N = nextInt(), M = nextInt();
		int[] graph = new int[N];
		for(int i = 0; i < M; i++){
			int a = nextInt() - 1, b = nextInt() - 1;
			graph[a] |= (1<<b);
			graph[b] |= (1<<a);
		}

		int[] bitcount = new int[1<<N];
		for(int i = 0; i < (1<<N); i++){
			bitcount[i] = bitcount[i>>1];
			if(i % 2 == 1) bitcount[i]++;
		}

		long[][] dp = new long[1<<N][N];
		for(long[] f : dp) Arrays.fill(f, 0);
		long ans = 0;
		for(int mask = 1; mask < (1<<N); mask++){
			for(int i = 0; i < N; i++)if((mask & (1<<i)) > 0){
				if(bitcount[mask] == 1) dp[mask][i] = 1;
				else{
					if(first(mask) != (1<<i)){
						for(int j = 0; j < N; j++)if((graph[i] & (1<<j)) > 0 && (mask & (1<<j)) > 0){
							dp[mask][i] += dp[mask - (1<<i)][j];
						}
					}
				}
				if(bitcount[mask] >= 3 && (graph[i] & first(mask)) > 0) ans += dp[mask][i];
			}
		}

		System.out.println(ans / 2);
    }

    int nextInt(){
        try{
            int c = System.in.read();
            if(c == -1) return c;
            while(c != '-' && (c < '0' || '9' < c)){
                c = System.in.read();
                if(c == -1) return c;
            }
            if(c == '-') return -nextInt();
            int res = 0;
            do{
                res *= 10;
                res += c - '0';
                c = System.in.read();
            }while('0' <= c && c <= '9');
            return res;
        }catch(Exception e){
            return -1;
        }
    }

    long nextLong(){
        try{
            int c = System.in.read();
            if(c == -1) return -1;
            while(c != '-' && (c < '0' || '9' < c)){
                c = System.in.read();
                if(c == -1) return -1;
            }
            if(c == '-') return -nextLong();
            long res = 0;
            do{
                res *= 10;
                res += c-'0';
                c = System.in.read();
            }while('0' <= c && c <= '9');
            return res;
        }catch(Exception e){
            return -1;
        }
    }

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

    String next(){
        try{
            StringBuilder res = new StringBuilder("");
            int c = System.in.read();
            while(Character.isWhitespace(c))
                c = System.in.read();
            do{
                res.append((char)c);
            }while(!Character.isWhitespace(c=System.in.read()));
            return res.toString();
        }catch(Exception e){
            return null;
        }
    }

    String nextLine(){
        try{
            StringBuilder res = new StringBuilder("");
            int c = System.in.read();
            while(c == '\r' || c == '\n')
                c = System.in.read();
            do{
                res.append((char)c);
                c = System.in.read();
            }while(c != '\r' && c != '\n');
            return res.toString();
        }catch(Exception e){
            return null;
        }
    }

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


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

public class ProblemD {

	static int N;
	static boolean[][] graph;

	public static void main(String[] args) throws IOException {
		BufferedReader s = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter out = new PrintWriter(System.out);
		String[] data = s.readLine().split(" ");
		int n = Integer.valueOf(data[0]);
		N = n;
		int m = Integer.valueOf(data[1]);
		graph = new boolean[n][n];
		for (int i = 0 ; i < m ; i++) {
			String[] line = s.readLine().split(" ");
			int a = Integer.valueOf(line[0])-1;
			int b = Integer.valueOf(line[1])-1;
			graph[a][b] = true;
			graph[b][a] = true;
		}

		long ans = 0;
		for (int i = 0 ; i < n ; i++) {
			ans += doit(i);
		}
		ans /= 2;

		out.println(ans);
		out.flush();
	}

	static long doit(int n) {
		long[][] dp = new long[1<<n][n];
		for (int i = 0 ; i < n ; i++) {
			if (graph[i][n]) {
				dp[1<<i][i] = 1;
			}
		}

		for (int i = 0 ; i < (1<<n) ; i++) {
			for (int j = 0 ; j < n ; j++) {
				if (dp[i][j] >= 1) {
					for (int k = 0 ; k < n ; k++) {
						if (graph[j][k] && (i & (1<<k)) == 0) {
							dp[i|1<<k][k] += dp[i][j];
						}
					}
				}
			}
		}

		long ret = 0;
		for (int i = 0 ; i < (1<<n) ; i++) {
			if (Integer.bitCount(i) >= 2) {
				for (int j = 0 ; j < n ; j++) {
					if (graph[j][n]) {
						ret += dp[i][j];
					}
				}
			}
		}
		return ret;
	}

	static void generateLarge() {
		System.out.println("19 171");
		for (int i = 1 ; i <= 19 ; i++) {
			for (int j = i+1 ; j <= 19 ; j++) {
				System.out.println(i + " " + j);
			}
		}
	}

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


/**
 * JUDGE_ID : 104262PN
 * User     : Денис
 * Date     : 09.05.11
 * Time     : 22:48
 * ICQ      : 785625
 * Email    : popokus@gmail.com
 */

import java.io.*;

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

    int nextInt() throws IOException {
        in.nextToken();
        return (int) in.nval;
    }

    String nextString() throws IOException {
        in.nextToken();
        return (String) in.sval;
    }

    StreamTokenizer in;
    Writer writer;
    Reader reader;

    void run() throws IOException {
        boolean oj = System.getProperty("ONLINE_JUDGE") != null;
        reader = oj ? new InputStreamReader(System.in, "ISO-8859-1") : new FileReader("input/is11_d.txt");
        writer = new OutputStreamWriter(System.out, "ISO-8859-1");
        in = new StreamTokenizer(new BufferedReader(reader));
        PrintWriter out = new PrintWriter(writer);
        int n = nextInt();
        int e = nextInt();
        boolean[][] is = new boolean[n + 1][n + 1];
        for (int i = 0; i < e;i++) {
            int a = nextInt() - 1;
            int b = nextInt() - 1;
            is[a][b] = true;
            is[b][a] = true;
        }
        // calculating dp
        long[] am = new long[n + 1];
                long[][] ways = new long[1 << (n - 1)][n];
                for (int start = 0; start < n; ++start) {
                    for (int mask = 0; mask < (1 << (n - start - 1)); ++mask)
                        for (int last = start; last < n; ++last) {
                            ways[mask][last - start] = 0;
                        }
                    ways[1 >> 1][0] = 1;
                    for (int mask = 1; mask < (1 << (n - start)); mask += 2) {
                        int cnt = 0;
                        int tmp = mask;
                        while (tmp > 0) {
                            ++cnt;
                            tmp = tmp & (tmp - 1);
                        }
                        for (int last = start; last < n; ++last)
                            if (ways[mask >> 1][last - start] > 0) {
                                long amm = ways[mask >> 1][last - start];
                                for (int i = start; i < n; ++i)
                                    if ((mask & (1 << (i - start))) == 0 && is[last][i]) {
                                        ways[(mask | (1 << (i - start))) >> 1][i - start] += amm;
                                    }
                                if (is[last][start])
                                    am[cnt] += ways[mask >> 1][last - start];
                            }
                    }
                }
                long res = 0;
                for (int cnt = 3; cnt <= n; ++cnt) {
                    if (am[cnt] % (2) != 0)
                        throw new RuntimeException();
                    res += am[cnt] / (2);
                }
        out.println(res);
        out.flush();
        out.close();
    }
}


import java.util.Scanner;

public class SimpleTask {

	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int n = scan.nextInt();
		int m = scan.nextInt();

		boolean[][] graph = new boolean[n][n];
		for (int i = 0; i < m; i++) {
			int u = scan.nextInt() - 1;
			int v = scan.nextInt() - 1;
			graph[u][v] = true;
			graph[v][u] = true;
		}

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

		for (int i = 0; i < n; i++)
			dp[1 << i][i] = 1;

		for (int mask = 1; mask < (1 << n); mask++) {

			int first = Integer.numberOfTrailingZeros(mask);

			for (int i = 0; i < n; i++) {
				if ((mask & (1 << i)) == 0 || first == i)
					continue;

				for (int j = 0; j < n; j++) {
					if (graph[i][j])
						dp[mask][i] += dp[mask ^ 1 << i][j];
				}

			}
		}
		long answer = 0;
		for (int mask = 1; mask < (1 << n); mask++) {
			if (Integer.bitCount(mask) < 3)
				continue;

			int first = Integer.numberOfTrailingZeros(mask);
			for (int i = 0; i < n; i++) {
				if (graph[first][i])
					answer += dp[mask][i];
			}
		}

		System.out.println(answer / 2);
		scan.close();
	}
}


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

public class CF {

	void realSolve() {
		int n = in.nextInt();
		int m = in.nextInt();
		boolean[][] f = new boolean[n][n];
		for (int i = 0; i < m; i++) {
			int fr = in.nextInt() - 1;
			int to = in.nextInt() - 1;
			f[fr][to] = f[to][fr] = true;
		}
		long[][] dp = new long[n][1 << n];
		for (int i = 0; i < n; i++)
			dp[i][1 << i] = 1;
		long res = 0;
		int[] len = new int[n + 1];
		for (int st = 0; st < 1 << n; st++) {
			int from = Integer.lowestOneBit(st);
			for (int i =0; i < n;i++)
				if (((1<<i) & st) != 0) {
					from =i;
					break;
				}
			for (int to = 0; to < n; to++)
				if (dp[to][st] != 0)
					for (int next = from; next < n; next++)
						if (f[to][next]
								&& ((((1 << next) & st) == 0) || next == from))
							if (next == from) {
								if (Integer.bitCount(st) > 2) {
									res += dp[to][st];
									len[Integer.bitCount(st)] += dp[to][st];
								}
							} else {
								dp[next][st | (1 << next)] += dp[to][st];
							}
		}
		out.println(res / 2);
	}

	private class InputReader {
		StringTokenizer st;
		BufferedReader br;

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

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

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

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

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

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

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

	InputReader in;
	PrintWriter out;

	void solve() {
		in = new InputReader(new File("object.in"));
		try {
			out = new PrintWriter(new File("object.out"));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}

		realSolve();

		out.close();
	}

	void solveIO() {
		in = new InputReader(System.in);
		out = new PrintWriter(System.out);

		realSolve();

		out.close();

	}

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


import java.util.Scanner;

public class SimpleTask {

	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int n = scan.nextInt();
		int m = scan.nextInt();

		boolean[][] graph = new boolean[n][n];
		for (int i = 0; i < m; i++) {
			int u = scan.nextInt() - 1;
			int v = scan.nextInt() - 1;
			graph[u][v] = true;
			graph[v][u] = true;
		}

		long[][] dp = new long[1 << n][n];
		long sum = 0;

		for (int i = 0; i < n; i++)
			dp[1 << i][i] = 1;

		for (int mask = 1; mask < (1 << n); mask++) {

			int first = Integer.numberOfTrailingZeros(mask);

			for (int i = 0; i < n; i++) {
				if ((mask & (1 << i)) == 0 || first == i)
					continue;

				for (int j = 0; j < n; j++) {
					if (graph[i][j] && (mask & (1 << j)) != 0)
						dp[mask][i] += dp[mask ^ 1 << i][j];
				}

				if (Integer.bitCount(mask) >= 3 && graph[i][first])
					sum += dp[mask][i];
			}

		}

		System.out.println(sum / 2);
		scan.close();
	}
}


import java.io.*;
import java.util.*;
public class Main{
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int m=sc.nextInt();
        int x,y;
        boolean graph[][]=new boolean[n][n];
        for(int i=0;i<m;i++){
            x=sc.nextInt()-1;
            y=sc.nextInt()-1;
            graph[x][y]=graph[y][x]=true;
        }
        long dp[][]=new long[1<<n][n];
        long res=0;
        for(int i=0;i<n;i++){
            dp[1<<i][i]=1;
        }
        for(int mask=1;mask<(1<<n);mask++){
            int first=-1;
            for(int f=0;f<n;f++){
                if((mask&(1<<f))!=0){
                    first=f;
                    break;
                }
            }
            for(int i=0;i<n;i++){
                if((mask&(1<<i))!=0&&i!=first){
                    for(int j=0;j<n;j++){
                        if(graph[j][i]&&((mask&1<<j)!=0)){
                            dp[mask][i]+=dp[mask^1<<i][j];
                        }
                    }
                }
                if(Integer.bitCount(mask)>2&&graph[first][i]){
                    res+=dp[mask][i];
                }
            }
        }

        System.out.println(res/2);
    }

}


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

public class P11D{
	static long mod=1000000007;

    public static void main(String[] args) throws Exception{
    	InputReader in = new InputReader(System.in);
    	PrintWriter pw=new PrintWriter(System.out);

    	//int t=in.readInt();
        //while(t-->0)
        //{

        int n=in.readInt();
        int m=in.readInt();
        boolean v[][]=new boolean[n][n];
        for(int i=0;i<m;i++)
        {
        	int x=in.readInt()-1;
        	int y=in.readInt()-1;
        	v[x][y]=true;
        	v[y][x]=true;
        }

       long dp[][]=new long[1<<n][n];
       for(int i=0;i<n;i++)
       {
    	   dp[1<<i][i]=1;
       }
       long ans=0;
    	for(int mask=1;mask<(1<<n);mask++)
    	{
    		int s=-1;
    		for(int i=0;i<n;i++)
    		{
    			if((mask&(1<<i))!=0)
    			{
    				s=i;
    				break;
    			}
    		}
    		for(int i=0;i<n;i++)
    		{
    			if(i!=s&&((1<<i)&mask)!=0)
    			{
    				for(int j=0;j<n;j++)
    				{
    					if((1<<j)!=0&&i!=j&&v[i][j])
    					{
    						int rem=(1<<i)^mask;
    						dp[mask][i]+=dp[rem][j];
    					}
    				}

    				int c=Integer.bitCount(mask);
    				if(c>=3&&v[i][s])
    				{
    					ans+=dp[mask][i];
    				}
    			}
    		}
    	}
    	ans/=2;
		pw.println(ans);

    	//}

    	pw.close();
    }

public static long gcd(long x,long y)
{
	if(x%y==0)
		return y;
	else
		return gcd(y,x%y);
}
public static int gcd(int x,int y)
{
	if(x%y==0)
		return y;
	else
		return gcd(y,x%y);
}
public static int abs(int a,int b)
{
	return (int)Math.abs(a-b);
}
public static long abs(long a,long b)
{
	return (long)Math.abs(a-b);
}
public static int max(int a,int b)
{
	if(a>b)
		return a;
	else
		return b;
}
public static int min(int a,int b)
{
	if(a>b)
		return b;
	else
		return a;
}
public static long max(long a,long b)
{
	if(a>b)
		return a;
	else
		return b;
}
public static long min(long a,long b)
{
	if(a>b)
		return b;
	else
		return a;
}

public static long pow(long n,long p,long m)
{
	 long  result = 1;
	  if(p==0)
	    return 1;
	if (p==1)
	    return n;
	while(p!=0)
	{
	    if(p%2==1)
	        result *= n;
	    if(result>=m)
	    result%=m;
	    p >>=1;
	    n*=n;
	    if(n>=m)
	    n%=m;
	}
	return result;
}
public static long pow(long n,long p)
{
	long  result = 1;
	  if(p==0)
	    return 1;
	if (p==1)
	    return n;
	while(p!=0)
	{
	    if(p%2==1)
	        result *= n;
	    p >>=1;
	    n*=n;
	}
	return result;

}
static class Pair implements Comparable<Pair>
{
	int a,b;
	Pair (int a,int b)
	{
		this.a=a;
		this.b=b;
	}

	public int compareTo(Pair o) {
		// TODO Auto-generated method stub
		if(this.a!=o.a)
		return Integer.compare(this.a,o.a);
		else
			return Integer.compare(this.b, o.b);
		//return 0;
	}
	public boolean equals(Object o) {
        if (o instanceof Pair) {
            Pair p = (Pair)o;
            return p.a == a && p.b == b;
        }
        return false;
    }
    public int hashCode() {
        return new Integer(a).hashCode() * 31 + new Integer(b).hashCode();
    }

}

static long sort(int a[])
{  int n=a.length;
	int b[]=new int[n];
	return mergeSort(a,b,0,n-1);}
static long mergeSort(int a[],int b[],long left,long right)
{ long c=0;if(left<right)
 {   long mid=left+(right-left)/2;
	 c= mergeSort(a,b,left,mid);
	 c+=mergeSort(a,b,mid+1,right);
	 c+=merge(a,b,left,mid+1,right); }
	return c;	 }
static long merge(int a[],int  b[],long left,long mid,long right)
{long c=0;int i=(int)left;int j=(int)mid; int k=(int)left;
while(i<=(int)mid-1&&j<=(int)right)
{ if(a[i]<=a[j]) {b[k++]=a[i++]; }
else	{ b[k++]=a[j++];c+=mid-i;}}
while (i <= (int)mid - 1)   b[k++] = a[i++];
while (j <= (int)right) b[k++] = a[j++];
for (i=(int)left; i <= (int)right; i++)
	a[i] = b[i];  return c;  }

public static int[] radixSort(int[] f)
{
	int[] to = new int[f.length];
	{
		int[] b = new int[65537];
		for(int i = 0;i < f.length;i++)b[1+(f[i]&0xffff)]++;
		for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
		for(int i = 0;i < f.length;i++)to[b[f[i]&0xffff]++] = f[i];
		int[] d = f; f = to;to = d;
	}
	{
		int[] b = new int[65537];
		for(int i = 0;i < f.length;i++)b[1+(f[i]>>>16)]++;
		for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
		for(int i = 0;i < f.length;i++)to[b[f[i]>>>16]++] = f[i];
		int[] d = f; f = to;to = d;
	}
	return f;
}
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 String readLine() {
        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 double readDouble() {
        int c = read();
        while (isSpaceChar(c))
            c = read();
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        double res = 0;
        while (!isSpaceChar(c) && c != '.') {
            if (c == 'e' || c == 'E')
                return res * Math.pow(10, readInt());
            if (c < '0' || c > '9')
                throw new InputMismatchException();
            res *= 10;
            res += c - '0';
            c = read();
        }
        if (c == '.') {
            c = read();
            double m = 1;
            while (!isSpaceChar(c)) {
                if (c == 'e' || c == 'E')
                    return res * Math.pow(10, readInt());
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                m /= 10;
                res += (c - '0') * m;
                c = read();
            }
        }
        return res * sgn;
    }
    public long readLong() {
        int c = read();
        while (isSpaceChar(c))
            c = read();
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        long res = 0;
        do {
            if (c < '0' || c > '9')
                throw new InputMismatchException();
            res *= 10;
            res += c - '0';
            c = read();
        } while (!isSpaceChar(c));
        return res * sgn;
    }
    public boolean isSpaceChar(int c)
    {
        if (filter != null)
            return filter.isSpaceChar(c);
        return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
    }

    public String next()
    {
        return readString();
    }

    public interface SpaceCharFilter
    {
        public boolean isSpaceChar(int ch);
    }
    public boolean isEndOfLine(int c) {
        return c == '\n' || c == '\r' || c == -1;
    }
}

//BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	//StringBuilder sb=new StringBuilder("");
	 //InputReader in = new InputReader(System.in);
	//PrintWriter pw=new PrintWriter(System.out);
	//String line=br.readLine().trim();

	//int t=Integer.parseInt(br.readLine());
  //	while(t-->0)
  	//{
  	//int n=Integer.parseInt(br.readLine());
	//long n=Long.parseLong(br.readLine());
	//String l[]=br.readLine().split(" ");
  //int m=Integer.parseInt(l[0]);
	//int k=Integer.parseInt(l[1]);
	//String l[]=br.readLine().split(" ");
	//l=br.readLine().split(" ");
	/*int a[]=new int[n];
	for(int i=0;i<n;i++)
	{
		a[i]=Integer.parseInt(l[i]);
	}*/
	   //System.out.println(" ");

	//}
}


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

public class Main implements Runnable {
	private void solution() throws IOException {
		int n = in.nextInt();
		int m = in.nextInt();
		boolean[][] adj = new boolean[n][n];
		long res = 0;
		for (int i = 0; i < m; ++i) {
			int x = in.nextInt();
			int y = in.nextInt();
			adj[x - 1][y - 1] = true;
			adj[y - 1][x - 1] = true;
		}
		for (int i = 0; i < n; ++i) {
			for (int j = i + 1; j < n; ++j) {
				if (adj[i][j]) {
					--res;
				}
			}
		}
		for (int i = 0; i < n; ++i) {
			long[][] dp = new long[1 << (n - i)][n - i];
			dp[0][0] = 1;
			for (int mask = 0; mask < (1 << (n - i)); ++mask) {
				for (int j = 0; j < n - i; ++j) {
					if (dp[mask][j] != 0) {
						for (int k = 0; k < n - i; ++k) {
							if (((mask >> k) & 1) == 0 && adj[j + i][k + i]) {
								dp[mask | (1 << k)][k] += dp[mask][j];
							}
						}
					}
				}
				if (((mask >> 0) & 1) != 0) {
					res += dp[mask][0];
				}
			}
		}
		out.println(res / 2);
	}

	public void run() {
		try {
			solution();
			in.reader.close();
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	private class Scanner {
		BufferedReader reader;
		StringTokenizer tokenizer;

		public Scanner(Reader reader) {
			this.reader = new BufferedReader(reader);
			this.tokenizer = new StringTokenizer("");
		}

		public boolean hasNext() throws IOException {
			while (!tokenizer.hasMoreTokens()) {
				String next = reader.readLine();
				if (next == null) {
					return false;
				}
				tokenizer = new StringTokenizer(next);
			}
			return true;
		}

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

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

		public String nextLine() throws IOException {
			tokenizer = new StringTokenizer("");
			return reader.readLine();
		}

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

	public static void main(String[] args) throws IOException {
		new Thread(null, new Main(), "", 1 << 28).start();
	}
	PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
	Scanner in = new Scanner(new InputStreamReader(System.in));
}


import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int n = scan.nextInt();
		int m = scan.nextInt();

		boolean[][] graph = new boolean[n][n];
		for (int i = 0; i < m; i++) {
			int u = scan.nextInt() - 1;
			int v = scan.nextInt() - 1;
			graph[u][v] = true;
			graph[v][u] = true;
		}

		long[][] dp = new long[1 << n][n];
		long sum = 0;

		for (int i = 0; i < n; i++)
			dp[1 << i][i] = 1;

		for (int mask = 1; mask < (1 << n); mask++) {

			int first = Integer.numberOfTrailingZeros(mask);

			for (int i = 0; i < n; i++) {
				if ((mask & (1 << i)) == 0 || first == i)
					continue;

				for (int j = 0; j < n; j++) {
					if (graph[i][j] && (mask & (1 << j)) != 0)
						dp[mask][i] += dp[mask ^ 1 << i][j];
				}

				if (Integer.bitCount(mask) >= 3 && graph[i][first])
					sum += dp[mask][i];
			}

		}

		System.out.println(sum / 2);
		scan.close();
	}
}