import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class C {

    static StringTokenizer st;
    static BufferedReader in;
    static PrintWriter pw;

    public static void main(String[] args) throws IOException {
        in = new BufferedReader(new InputStreamReader(System.in));
        pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
        int n = nextInt();
        int m = nextInt();
        int[]a = new int[n+1];
        for (int i = 1; i <= n; i++) {
            a[i] = nextInt();
        }
        long[]cnt = new long[31];
        for (int i = 1; i <= m; i++) {
            cnt[nextInt()]++;
        }
        long[]s = new long[31];
        int e = 0;
        for (int i = 1; i <= n; i++) {
            int q = a[i];
            for (int j = 30; j >= 0; j--) {
                e = (1 << j);
                s[j] += q / e;
                q %= e;
            }
        }
        for (int i = 0; i <= 30; i++) {
            if (s[i] < cnt[i]) {
                for (int j = i+1; j <= 30; j++) {
                    long add = (long)s[j] * (1 << (j-i));
                    if (s[i]+add >= cnt[i]) {
                        s[j] = 0;
                        long qol = (1 << i) * (long)(add-(cnt[i]-s[i]));
                        for (int k = j; k >= 0; k--) {
                            e = (1 << k);
                            s[k] += qol / e;
                            qol %= e;
                        }
                        s[i] = cnt[i];
                        break;
                    }
                    else {
                        s[i] += add;
                        s[j] = 0;
                    }
                }
            }
        }
        long sum = 0;
        for (int i = 0; i <= 30; i++) {
            if (s[i] < cnt[i]) {
                sum += s[i];
                System.out.println(sum);
                return;
            }
            sum += cnt[i];
        }
        System.out.println(sum);
        pw.close();
    }
    private static int nextInt() throws IOException{
        return Integer.parseInt(next());
    }

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

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

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

import java.io.*;

import static java.lang.Math.*;
import java.util.*;
import static java.util.Arrays.fill;
import static java.util.Arrays.sort;

public class Main {
	public static void main(String[] args) {
		if(new File("input.txt").exists())
			try {
				System.setIn(new FileInputStream("input.txt"));
			} catch (FileNotFoundException e1) {
				e1.printStackTrace();
			}
		new Thread(null, new Runnable() {
			public void run() {
				try {
					new Main().run();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}, "kek", 1 << 23).start();
	}

	BufferedReader in;
	PrintWriter out;
	StringTokenizer st = new StringTokenizer("");

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

	final int off = 31;
	int b[];
	int n, m;
	int step = 1000;

	long preA[] = new long[off];

	void solve() throws IOException{

		n = nextInt();
		m = nextInt();
		b = new int[m];
		int sz = m / step + 1;

		for(int i = 0; i < n; i++){
			int x = nextInt();
			for(int k = 0; k < off; k++)
				if((x & (1 << k)) != 0)
					preA[k]++;
		}
		for(int i = 0; i < m; i++)
			b[i] = nextInt();

		sort(b);
		int answer = 0;
		int le = 0;
		int ri = m;
		while (le <= ri) {
			int mid = (le + ri) >> 1;
			if (solve(mid)) {
				answer = max(answer, mid);
				le = mid + 1;
			} else {
				ri = mid - 1;
			}
		}
		out.println(answer);

	}
	boolean solve(int count){
		long cntA[] = new long[off];
		long cntB[] = new long[off];
		for(int k = 0; k < off; k++)
			cntA[k] = preA[k];

		for(int i = 0; i < count; i++){
			cntB[b[i]]++;
		}
		for(int k = off - 1; k > 0; k--){
			long z = min(cntA[k], cntB[k]);
			cntA[k] -= z;
			cntB[k] -= z;
			if(cntB[k] != 0) return false;
			cntA[k - 1] += 2 * cntA[k];
		}

		return cntA[0] >= cntB[0];
	}

	String nextToken() throws IOException{
		while(!st.hasMoreTokens())
			st = new StringTokenizer(in.readLine());
		return st.nextToken();
	}
	long nextLong() throws IOException{
		return Long.parseLong(nextToken());
	}
	int nextInt() throws IOException{
		return Integer.parseInt(nextToken());
	}
	double nextDouble() throws IOException{
		return Double.parseDouble(nextToken());
	}
}

import java.io.*;
import java.util.*;
public class C309 {
public static void main(String[] args) throws IOException {
	input.init(System.in);
	PrintWriter out = new PrintWriter(System.out);
	int n = input.nextInt();
	int m = input.nextInt();
	int[] as = new int[n];
	for(int i = 0; i<n; i++) as[i] = input.nextInt();
	Arrays.sort(as);
	int[] fs = new int[32];
	for(int i = 0; i<m; i++) fs[input.nextInt()]++;
	int[] c = new int[32];
	for(int i = 0; i<32; i++) c[i] = fs[i];
	long res = 0;
	for(int i = n-1; i>=0; i--)
	{
		for(int j = 31; j>=0; j--)
		{
			while(as[i] >= (1<<j) && fs[j] > 0)
			{
				fs[j]--;
				as[i] -= (1<<j);
				res += (1<<j);
			}
		}
	}
	//t.println(res);
	int x = 0;
	for(int i = 0; i<32; i++)
	{
		long min = Math.min(c[i], res / (1<<i));
		x += min;
		res -= (1<<i) * min;
	}
	out.println(x);
	out.close();
}

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

	static void init(InputStream input) {
		reader = new BufferedReader(new InputStreamReader(input));
		tokenizer = new StringTokenizer("");
	}

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

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

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

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

import java.io.InputStreamReader;
import java.io.IOException;
import java.util.*;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.io.InputStream;

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

class TaskC {
    public void solve(int testNumber, FastScanner in, FastPrinter out) {
        int n = in.nextInt();
        int m = in.nextInt();
        int[] boxes = new int[31];
        for (int i = 0; i < n; i++) {
            int x = in.nextInt();
            while (x > 0) {
                boxes[Integer.numberOfTrailingZeros(x)]++;
                x &= x - 1;
            }
        }
        int[] count = new int[31];
        for (int i = 0; i < m; i++) {
            count[in.nextInt()]++;
        }
        int[] got = new int[31];
        for (int i = 30; i >= 0; i--) {
            int cur = count[i];
            if (cur == 0) continue;
            for (int j = 30; j >= i; j--) {
                if (boxes[j] == 0) continue;
                int cn = boxes[j];
                int cn2 = (1 << j) >> i;
                int boxesToGet = cur / cn2;
                if (boxesToGet > cn) {
                    boxes[j] = 0;
                    got[i] += cn * cn2;
                    cur -= cn * cn2;
                } else {
                    boxes[j] -= boxesToGet;
                    got[i] += boxesToGet * cn2;
                    cur -= boxesToGet * cn2;
                }
                if (boxes[j] > 0 && cur > 0 && cur < cn2) {
                    int left = (1 << j) - cur * (1 << i);
                    boxes[j]--;
                    got[i] += cur;
                    cur = 0;
                    while (left > 0) {
                        boxes[Integer.numberOfTrailingZeros(left)]++;
                        left &= left - 1;
                    }
                }
            }
            for (int j = 30; j > i; j--) {
                int cn = got[j];
                if (cn == 0) continue;
                int cn2 = (1 << j) >> i;
                int boxesToGet = cur / cn2;
                if (boxesToGet > cn) {
                    got[j] = 0;
                    got[i] += cn * cn2;
                    cur -= cn * cn2;
                } else {
                    got[j] -= boxesToGet;
                    got[i] += boxesToGet * cn2;
                    cur -= boxesToGet * cn2;
                }
                if (cur > 0 && cur < cn2 && got[j] > 0) {
                    int left = (1 << j) - cur * (1 << i);
                    got[j]--;
                    got[i] += cur;
                    cur = 0;
                    while (left > 0) {
                        boxes[Integer.numberOfTrailingZeros(left)]++;
                        left &= left - 1;
                    }
                }
            }
        }
        int ans = 0;
        for (int i : got) ans += i;
        out.println(ans);
    }
}

class FastScanner extends BufferedReader {

    public FastScanner(InputStream is) {
        super(new InputStreamReader(is));
    }

    public int read() {
        try {
            int ret = super.read();
//            if (isEOF && ret < 0) {
//                throw new InputMismatchException();
//            }
//            isEOF = ret == -1;
            return ret;
        } catch (IOException e) {
            throw new InputMismatchException();
        }
    }

    static boolean isWhiteSpace(int c) {
        return c >= 0 && c <= 32;
    }

    public int nextInt() {
        int c = read();
        while (isWhiteSpace(c)) {
            c = read();
        }
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        int ret = 0;
        while (c >= 0 && !isWhiteSpace(c)) {
            if (c < '0' || c > '9') {
                throw new NumberFormatException("digit expected " + (char) c
                        + " found");
            }
            ret = ret * 10 + c - '0';
            c = read();
        }
        return ret * sgn;
    }

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

    }

class FastPrinter extends PrintWriter {

    public FastPrinter(OutputStream out) {
        super(out);
    }

    public FastPrinter(Writer out) {
        super(out);
    }

}

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

public class Main {

	void solve() {
		int n = sc.nextInt();
		int m = sc.nextInt();
		int[] a = sc.nextIntArray(n);
		int[] b = sc.nextIntArray(m);

		// shuffle(a);sort(a);
		shuffle(b);sort(b);

		int S = 33;
		int[] have = new int[S];
		for (int x : a) {
			for (int i = 0; i < S; i++) {
				if ((x & 1) == 1) have[i]++;
				x >>= 1;
			}
		}

		tr(have);

		long ans = 0;
		for (int y : b) {
			if (have[y] > 0) {
				ans++;
				have[y]--;
			} else {
				int i = y + 1;
				for (; i < S; i++) {
					if (have[i] > 0) break;
				}
				if (i < S) {
					++ans;
					have[i]--;
					long t = (1L << i) - (1L << y);
					for (int j = 0; j < S; j++) {
						if ((t & 1) == 1) have[j]++;
						t >>= 1;
					}
				}
			}
		}

		out.println(ans);

	}
	void shuffle(int[] a) {
		int n = a.length;
		Random random = new Random(System.currentTimeMillis());
		for (int i = 0; i < n; i++) {
			int j = i + random.nextInt(n - i);
			int t = a[i];
			a[i] = a[j];
			a[j] = t;
		}
	}

	public static void main(String[] args) throws Exception {
		Class<?> here = new Object(){}.getClass().getEnclosingClass();
		try {
			String packageName = here.getPackage().getName();
			packageName = "src/" + packageName.replaceAll("\\.", "/") + "/";
			System.setIn(new FileInputStream(packageName + "input.txt"));
//			System.setOut(new PrintStream(new FileOutputStream(packageName + "output.txt")));
		} catch (FileNotFoundException e) {
		} catch (NullPointerException e) {
		}

		Object o = Class.forName(here.getName()).newInstance();
		o.getClass().getMethod("run").invoke(o);
	}

	static void tr(Object... os) {
		System.err.println(deepToString(os));
	}

	MyScanner sc = null;
	PrintWriter out = null;
	public void run() throws Exception {
		sc = new MyScanner(System.in);
		out = new PrintWriter(System.out);
		for (;sc.hasNext();) {
			solve();
			out.flush();
		}
		out.close();
	}

	void print(int[] a) {
		out.print(a[0]);
		for (int i = 1; i < a.length; i++) out.print(" " + a[i]);
		out.println();
	}

	class MyScanner {
		String line;
		BufferedReader reader;
		StringTokenizer tokenizer;

		public MyScanner(InputStream stream) {
			reader = new BufferedReader(new InputStreamReader(stream));
			tokenizer = null;
		}
		public void eat() {
			while (tokenizer == null || !tokenizer.hasMoreTokens()) {
				try {
					line = reader.readLine();
					if (line == null) {
						tokenizer = null;
						return;
					}
					tokenizer = new StringTokenizer(line);
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			}
		}
		public String next() {
			eat();
			return tokenizer.nextToken();
		}
		public String nextLine() {
			try {
				return reader.readLine();
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		public boolean hasNext() {
			eat();
			return (tokenizer != null && tokenizer.hasMoreElements());
		}
		public int nextInt() {
			return Integer.parseInt(next());
		}
		public long nextLong() {
			return Long.parseLong(next());
		}
		public double nextDouble() {
			return Double.parseDouble(next());
		}
		public int[] nextIntArray(int n) {
			int[] a = new int[n];
			for (int i = 0; i < n; i++) a[i] = nextInt();
			return a;
		}
	}
}

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

public class C {

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

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

		int[] a = new int[n];

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

		int[] cnt = new int[30];
		for (int i = 0; i < m; i++) {
			cnt[nextInt()]++;
		}

		Queue<Integer> q = new ArrayDeque<>();

		int ans = 0;
		for (int sz = 0; sz < 30; sz++) {
			int cur = cnt[sz];
			for (int i = 0; i < cur; i++)
				q.add(1);

			for (int i = 0; i < n; i++) {
				if ((a[i] & 1) == 1 && !q.isEmpty()) {
					a[i]--;
					ans += q.poll();
				}
				a[i] >>= 1;
			}
			int curSz = q.size();
			for (int i = 0; i < curSz; ) {
				int sum = q.poll();
				i++;
				if (i != curSz) {
					sum += q.poll();
					i++;
				}
				q.add(sum);
			}
		}

		out.println(ans);
	}

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

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

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

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

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

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

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

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

public class C {

	private void add(int[] p, int a) {
		for (int j = 0; j < 30; j++) {
			if ((a & (1 << j)) != 0) {
				p[j]++;
			}
		}
	}

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

		int[] p = new int[30];
		for (int i = 0; i < n; i++) {
			add(p, nextInt());
		}

		int[] b = new int[30];
		for (int i = 0; i < m; i++) {
			b[nextInt()]++;
		}

		int res = 0;
		for (int i = 0; i < 30; i++) {
			int d = 1;
			for (int j = i; j < 30; j++) {
				if (p[j] * d >= b[i]) {
					res += b[i];
					p[j] -= b[i] / d;
					if (b[i] % d != 0) {
						p[j]--;
						add(p, (1 << j) - (b[i] % d) * (1 << i));
					}
					break;
				} else {
					b[i] -= p[j] * d;
					res += p[j] * d;
					p[j] = 0;
					d *= 2;
				}
			}
		}

		println(res);
	}

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

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

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

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

	private void print(Object o) {
		writer.print(o);
	}

	private void println(Object o) {
		writer.println(o);
	}

	private void printf(String format, Object... o) {
		writer.printf(format, o);
	}

	public static void main(String[] args) {
		long time = System.currentTimeMillis();
		Locale.setDefault(Locale.US);
		new C().run();
		System.err.printf("%.3f\n", 1e-3 * (System.currentTimeMillis() - time));
	}

	BufferedReader reader;
	StringTokenizer tokenizer;
	PrintWriter writer;

	private void run() {
		try {
			reader = new BufferedReader(new InputStreamReader(System.in));
			writer = new PrintWriter(System.out);
			solve();
			reader.close();
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(13);
		}
	}
}

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;

public class C {
	static boolean bit_set(int set, int bit) {
		return ((set>>bit)&1)==1;
	}
	static int LIM = 1000*1000*30;
	static int[] WANT;
	static int[] HAVE;
	static void push_down() {
		for(int i=29; i>=1; i--) {
			if(HAVE[i] > WANT[i]) {
				int amt = HAVE[i]-WANT[i];
				HAVE[i]-=amt;
				HAVE[i-1] = Math.min(LIM, HAVE[i-1]+2*amt);
			}
		}
	}

	static int need(int bit) {
		int need = 0;
		for(int i=0; i<bit; i++) {
			need = (need+1)/2;
			if(WANT[i] > HAVE[i])
				need += WANT[i]-HAVE[i];
		}
		need = (need+1)/2;
		return need;
	}

	static int i(String s) { return Integer.parseInt(s); }
	public static void main(String[] args) throws Exception {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		String[] arr = in.readLine().split(" ");
		int n = i(arr[0]);
		int m = i(arr[1]);

		HAVE = new int[30];
		WANT = new int[30];

		arr = in.readLine().split(" ");
		for(int i=0; i<n; i++) {
			int val = i(arr[i]);
			for(int bit=0; bit<30; bit++)
				if(bit_set(val, bit))
					HAVE[bit]++;
		}

		arr = in.readLine().split(" ");
		for(int i=0; i<m; i++)
			WANT[i(arr[i])]++;

		push_down();
		//System.out.println(Arrays.toString(WANT));
		//System.out.println(Arrays.toString(HAVE));
		for(int i=29; i>=1; i--) {
			int amt = Math.min(need(i), HAVE[i]);
			HAVE[i] -= amt;
			HAVE[i-1] = Math.min(LIM, HAVE[i-1]+2*amt);
			push_down();
		}
		//System.out.println(Arrays.toString(WANT));
		//System.out.println(Arrays.toString(HAVE));

		int ans = 0;
		for(int i=0; i<30; i++)
			ans += Math.min(WANT[i], HAVE[i]);
		System.out.println(ans);
	}
}

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.StringTokenizer;

public class Solve6 {

    public static void main(String[] args) throws IOException {
        PrintWriter pw = new PrintWriter(System.out);
        new Solve6().solve(pw);
        pw.flush();
        pw.close();
    }

    public void solve(PrintWriter pw) throws IOException {
        FastReader sc = new FastReader();
        int n = sc.nextInt(), m = sc.nextInt();
        long[] a = new long[n], b = new long[m];
        for (int i = 0; i < n; i++) {
            a[i] = sc.nextLong();
        }
        for (int i = 0; i < m; i++) {
            b[i] = 1 << sc.nextInt();
        }
        int[] x = getBitsFrequency(a), y = getBitsFrequency(b);
        int ans = m;
        for (int i = 0; i <= 30; i++) {
            for (int j = i, k = 1; j <= 30 && y[i] > 0; j++, k *= 2) {
                int z = y[i] / k + (y[i] % k == 0 ? 0 : 1);
                if (x[j] < z) {
                    y[i] -= x[j] * k;
                    x[j] = 0;
                } else {
                    x[j] -= z;
                    if (y[i] % k != 0) {
                        y[i] -= y[i] / k * k;
                        int temp = (1 << j) - (y[i] * (1 << i));
                        for (int w = 0; w <= 30; w++) {
                            if ((temp & (1 << w)) != 0) {
                                ++x[w];
                            }
                        }
                    }
                    y[i] = 0;
                }
            }
        }
        for (int i = 0; i <= 30; i++) {
            ans -= y[i];
        }
        pw.println(ans);
    }

    //bits starts from 0-index
    public int[] getBitsFrequency(long[] arr) {
        final int BITS_NUMBER = 32;
        int[] freq = new int[BITS_NUMBER];
        for (long x : arr) {
            for (int i = 0; i < BITS_NUMBER; i++) {
                if ((x & (1L << i)) != 0) {
                    ++freq[i];
                }
            }
        }
        return freq;

    }

    static class FastReader {

        BufferedReader br;
        StringTokenizer st;

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

        public FastReader(String s) {
            try {
                br = new BufferedReader(new FileReader(s));
            } catch (FileNotFoundException e) {
            }
        }

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

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

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

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

        public String nextLine() {
            try {
                return br.readLine();
            } catch (Exception e) {
            }
            return null;
        }

        public boolean hasNext() throws IOException {
            if (st != null && st.hasMoreTokens()) {
                return true;
            }
            String s = br.readLine();
            if (s == null || s.isEmpty()) {
                return false;
            }
            st = new StringTokenizer(s);
            return true;
        }
    }
}

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

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

class C {
	public void solve(int testNumber, InputReader in, OutputWriter out) {
		int n = in.nextInt(), m = in.nextInt();
		//int n = 1000000, m = 1000000;
		Random rand = new Random(42);
		ArrayList<Integer> a = new ArrayList<>(n);
		int[] countB = new int[31];
		for (int i = 0; i < n; ++i) {
			a.add(in.nextInt());
			//a.add(rand.nextInt(1000000000));
		}
		//Collections.sort(a);
		long[] canCount = new long[31];
		for (int curSize : a) {
			int cur = curSize;
			for (int size = 30; size >= 0; --size) {
				while (cur >= (1 << size)) {
					cur -= 1 << size;
					++canCount[size];
				}
			}
		}
		for (int i = 0; i < m; ++i) {
			++countB[in.nextInt()];
			//++countB[rand.nextInt(30)];
		}
		int ans = 0;
		outer: for (int bSize = 0; bSize < countB.length; ++bSize) {
			for (int it = 0; it < countB[bSize]; ++it) {
				int ind = bSize;
				while (ind < canCount.length && canCount[ind] == 0) {
					++ind;
				}
				if (ind == canCount.length) {
					break outer;
				}
				while (ind > bSize) {
					--canCount[ind];
					canCount[ind - 1] += 2;
					--ind;
				}
				--canCount[bSize];
				++ans;
			}
		}
		out.println(ans);
		//canDo(a, countB.clone(), 3);
		/*int lo = 0, hi = m + 1;
		while (hi - lo > 1) {
			int mid = (lo + hi) / 2;
			if (canDo(a, countB.clone(), mid)) {
				lo = mid;
			} else {
				hi = mid;
			}
		}
		out.println(lo);*/
		/*int curIndex = 0, curLeft = a.get(curIndex);
		int ans = 0;
		outer: for (int curArray = 0; curArray < countB.length; ++curArray) {
			for (int it = 0; it < countB[curArray]; ++it) {
				int size = 1 << curArray;
				while (curLeft < size) {
					++curIndex;
					if (curIndex == a.size()) {
						curLeft = 0;
						break;
					} else {
						curLeft = a.get(curIndex);
					}
				}
				if (curLeft < size) {
					break outer;
				} else {
					++ans;
					curLeft -= size;
				}
			}
		}
		out.println(ans);*/
	}

	}

class InputReader {
	private final BufferedReader reader;
	private StringTokenizer tokenizer;

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

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

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

	}

class OutputWriter extends PrintWriter {

	public OutputWriter(Writer out) {
		super(out);
	}

	public OutputWriter(OutputStream out) {
		super(out);
	}

	}

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
import java.util.InputMismatchException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.NoSuchElementException;
import java.io.Writer;
import java.math.BigInteger;
import java.io.InputStream;

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

class TaskC {
    public void solve(int testNumber, InputReader in, OutputWriter out) {
		int[] qtyBits = new int[30];
		int[] qtyRequests = new int[30];
		int count = in.readInt();
		int requestCount = in.readInt();
		for (int i = 0; i < count; i++) {
			int cell = in.readInt();
			for (int j = 0; j < 30; j++) {
				if ((cell >> j & 1) == 1)
					qtyBits[j]++;
			}
		}
		for (int i = 0; i < requestCount; i++)
			qtyRequests[in.readInt()]++;
		int answer = 0;
		IntList weights = new IntArrayList();
		for (int i = 0; i < 30; i++) {
			for (int j = 0; j < qtyRequests[i]; j++)
				weights.add(1);
			for (int j = 0; j < weights.size() && j < qtyBits[i]; j++)
				answer += weights.get(j);
			IntList newWeights = new IntArrayList();
			for (int j = qtyBits[i]; j < weights.size(); j += 2) {
				int totalWeight = weights.get(j);
				if (j + 1 < weights.size())
					totalWeight += weights.get(j + 1);
				newWeights.add(totalWeight);
			}
			weights = newWeights;
		}
		out.printLine(answer);
    }
}

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

class OutputWriter {
	private final PrintWriter writer;

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

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

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

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

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

	}

abstract class IntList extends IntCollection implements Comparable<IntList> {
	private static final int INSERTION_THRESHOLD = 8;

	public abstract int get(int index);
	public abstract void set(int index, int value);

	public IntIterator iterator() {
		return new IntIterator() {
			private int size = size();
			private int index = 0;

			public int value() throws NoSuchElementException {
				if (!isValid())
					throw new NoSuchElementException();
				return get(index);
			}

			public void advance() throws NoSuchElementException {
				if (!isValid())
					throw new NoSuchElementException();
				index++;
			}

			public boolean isValid() {
				return index < size;
			}
		};
	}

	private void swap(int first, int second) {
		if (first == second)
			return;
		int temp = get(first);
		set(first, get(second));
		set(second, temp);
	}

	public IntSortedList inPlaceSort(IntComparator comparator) {
		quickSort(0, size() - 1, size(), comparator);
		return new IntSortedArray(this, comparator);
	}

	private void quickSort(int from, int to, int remaining, IntComparator comparator) {
		if (to - from < INSERTION_THRESHOLD) {
			insertionSort(from, to, comparator);
			return;
		}
		if (remaining == 0) {
			heapSort(from, to, comparator);
			return;
		}
		remaining >>= 1;
		int pivotIndex = (from + to) >> 1;
		int pivot = get(pivotIndex);
		swap(pivotIndex, to);
		int storeIndex = from;
		int equalIndex = to;
		for (int i = from; i < equalIndex; i++) {
			int value = comparator.compare(get(i), pivot);
			if (value < 0)
				swap(storeIndex++, i);
			else if (value == 0)
				swap(--equalIndex, i--);
		}
		quickSort(from, storeIndex - 1, remaining, comparator);
		for (int i = equalIndex; i <= to; i++)
			swap(storeIndex++, i);
		quickSort(storeIndex, to, remaining, comparator);
	}

	private void heapSort(int from, int to, IntComparator comparator) {
		for (int i = (to + from - 1) >> 1; i >= from; i--)
			siftDown(i, to, comparator, from);
		for (int i = to; i > from; i--) {
			swap(from, i);
			siftDown(from, i - 1, comparator, from);
		}
	}

	private void siftDown(int start, int end, IntComparator comparator, int delta) {
		int value = get(start);
		while (true) {
			int child = ((start - delta) << 1) + 1 + delta;
			if (child > end)
				return;
			int childValue = get(child);
			if (child + 1 <= end) {
				int otherValue = get(child + 1);
				if (comparator.compare(otherValue, childValue) > 0) {
					child++;
					childValue = otherValue;
				}
			}
			if (comparator.compare(value, childValue) >= 0)
				return;
			swap(start, child);
			start = child;
		}
	}

	private void insertionSort(int from, int to, IntComparator comparator) {
		for (int i = from + 1; i <= to; i++) {
			int value = get(i);
			for (int j = i - 1; j >= from; j--) {
				if (comparator.compare(get(j), value) <= 0)
					break;
				swap(j, j + 1);
			}
		}
	}

	public IntSortedList sort(IntComparator comparator) {
		return new IntArray(this).inPlaceSort(comparator);
	}

	public int hashCode() {
		int hashCode = 1;
		for (IntIterator i = iterator(); i.isValid(); i.advance())
			hashCode = 31 * hashCode + i.value();
		return hashCode;
	}

	public boolean equals(Object obj) {
		if (!(obj instanceof IntList))
			return false;
		IntList list = (IntList)obj;
		if (list.size() != size())
			return false;
		IntIterator i = iterator();
		IntIterator j = list.iterator();
		while (i.isValid()) {
			if (i.value() != j.value())
				return false;
			i.advance();
			j.advance();
		}
		return true;
	}

	public int compareTo(IntList o) {
		IntIterator i = iterator();
		IntIterator j = o.iterator();
		while (true) {
			if (i.isValid()) {
				if (j.isValid()) {
					if (i.value() != j.value()) {
						if (i.value() < j.value())
							return -1;
						else
							return 1;
					}
				} else
					return 1;
			} else {
				if (j.isValid())
					return -1;
				else
					return 0;
			}
			i.advance();
			j.advance();
		}
	}

	}

class IntArrayList extends IntList {
	private int[] array;
	private int size;

	public IntArrayList() {
		this(10);
	}

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

	public int get(int index) {
		if (index >= size)
			throw new IndexOutOfBoundsException();
		return array[index];
	}

	public void set(int index, int value) {
		if (index >= size)
			throw new IndexOutOfBoundsException();
		array[index] = value;
	}

	public int size() {
		return size;
	}

	public void add(int value) {
		ensureCapacity(size + 1);
		array[size++] = value;
	}

	private void ensureCapacity(int newCapacity) {
		if (newCapacity > array.length) {
			int[] newArray = new int[Math.max(newCapacity, array.length << 1)];
			System.arraycopy(array, 0, newArray, 0, size);
			array = newArray;
		}
	}

	}

abstract class IntCollection {
	public abstract IntIterator iterator();
	public abstract int size();
	public abstract void add(int value);

	}

interface IntIterator {
	public int value() throws NoSuchElementException;
	/*
	 * @throws NoSuchElementException only if iterator already invalid
	 */
	public void advance() throws NoSuchElementException;
	public boolean isValid();
}

interface IntComparator {
    public static final IntComparator DEFAULT = new IntComparator() {
        public int compare(int first, int second) {
            if (first < second)
                return -1;
            if (first > second)
                return 1;
            return 0;
        }
    };

	public int compare(int first, int second);
}

abstract class IntSortedList extends IntList {
	protected final IntComparator comparator;

	protected IntSortedList(IntComparator comparator) {
		this.comparator = comparator;
	}

	public void set(int index, int value) {
		throw new UnsupportedOperationException();
	}

	public void add(int value) {
		throw new UnsupportedOperationException();
	}

	public IntSortedList inPlaceSort(IntComparator comparator) {
		if (comparator == this.comparator)
			return this;
		throw new UnsupportedOperationException();
	}

	public IntSortedList sort(IntComparator comparator) {
		if (comparator == this.comparator)
			return this;
		return super.sort(comparator);
	}

	protected void ensureSorted() {
		int size = size();
		if (size == 0)
			return;
		int last = get(0);
		for (int i = 1; i < size; i++) {
			int current = get(i);
			if (comparator.compare(last, current) > 0)
				throw new IllegalArgumentException();
			last = current;
		}
	}

	}

class IntSortedArray extends IntSortedList {
	private final int[] array;

	public IntSortedArray(int[] array) {
		this(array, IntComparator.DEFAULT);
	}

	public IntSortedArray(IntCollection collection) {
		this(collection, IntComparator.DEFAULT);
	}

	public IntSortedArray(int[] array, IntComparator comparator) {
		super(comparator);
		this.array = array;
		ensureSorted();
	}

	public IntSortedArray(IntCollection collection, IntComparator comparator) {
		super(comparator);
		array = new int[collection.size()];
		int i = 0;
		for (IntIterator iterator = collection.iterator(); iterator.isValid(); iterator.advance())
			array[i++] = iterator.value();
		ensureSorted();
	}

	public int get(int index) {
		return array[index];
	}

	public int size() {
		return array.length;
	}
}

class IntArray extends IntList {
	private final int[] array;

	public IntArray(int[] array) {
		this.array = array;
	}

	public IntArray(IntCollection collection) {
		array = new int[collection.size()];
		int i = 0;
		for (IntIterator iterator = collection.iterator(); iterator.isValid(); iterator.advance())
			array[i++] = iterator.value();
	}

	public int get(int index) {
		return array[index];
	}

	public void set(int index, int value) {
		array[index] = value;
	}

	public int size() {
		return array.length;
	}

	public void add(int value) {
		throw new UnsupportedOperationException();
	}

	}

import static java.lang.Double.parseDouble;
import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.lang.Math.min;
import static java.lang.System.exit;

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

public class C {

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

	static void solve() throws Exception {
		int n = nextInt();
		int m = nextInt();
		int a[] = new int[30];
		for (int i = 0; i < n; i++) {
			int cur = nextInt();
			for (int j = 0; j < 30; j++) {
				if ((cur & (1 << j)) != 0) {
					++a[j];
				}
			}
		}
		int b[] = new int[30];
		for (int i = 0; i < m; i++) {
			++b[nextInt()];
		}
		int ans = 0;
		for (int i = 0; i < 30; i++) {
			for (int j = i; j < 30; j++) {
				if (b[i] == 0) {
					break;
				}
				long have = (long) a[j] << (j - i);
				int take = (int) min(b[i], have);
				b[i] -= take;
				ans += take;
				have -= take;
				a[j] = (int) (have >> (j - i));
				for (int k = i; k < j; k++) {
					if ((have & (1 << (k - i))) != 0) {
						++a[k];
					}
				}
			}
			if (b[i] != 0) {
				break;
			}
		}
		out.print(ans);
	}

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

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

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

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

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

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

public class C {
	BufferedReader br;
	StringTokenizer in;
	PrintWriter out;

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

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

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

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

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

		long[] cnt = new long[30];

		for (int i = 0; i < n; i++) {
			int z = nextInt();
			for (int j = 29; j >= 0; j--) {
				if (z >= 1 << j) {
					z -= 1 << j;
					cnt[j]++;
				}
			}
		}

		int[] c = new int[30];
		for (int i = 0; i < m; i++) {
			c[nextInt()]++;
		}

		int ans = 0;
		for (int i = 0; i < 30; i++) {
			boolean good = true;
			while (c[i] > 0) {
				int j = i;
				while (j < 30 && cnt[j] == 0) {
					j++;
				}

				if (j == 30) {
					good = false;
					break;
				}

				for (int k = j; k > i; k--) {
					cnt[k]--;
					cnt[k - 1] += 2;
				}

				cnt[i]--;
				ans++;
				c[i]--;
			}
			if (!good)
				break;
		}

		out.println(ans);
	}

	public void run() {
		try {
			br = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);

			solve();

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

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

import java.io.*;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.util.Map.Entry;

public class Main implements Runnable {
    static final int MOD = (int) 1e9 + 7;
    static final int MI = (int) 1e9;
    static final long ML = (long) 1e18;
    static final Reader in = new Reader();
    static final PrintWriter out = new PrintWriter(System.out);
    StringBuilder answer = new StringBuilder();
    Random random = new Random(751454315315L + System.currentTimeMillis());

    public static void main(String[] args) {
        new Thread(null, new Main(), "persefone", 1 << 28).start();
    }

    @Override
    public void run() {
        solve();
        printf();
        flush();
    }

    void solve() {
        int n = in.nextInt();
        int m = in.nextInt();
        int[] a = new int[31];
        for (int i = 0; i < n; i++) {
            int x = in.nextInt();
            for (int j = 0; j < 30; j++) {
                if ((x & (1 << j)) > 0) {
                    a[j]++;
                }
            }
        }
        int[] b = new int[31];
        for (int i = 0; i < m; i++) {
            b[in.nextInt()]++;
        }
        int low = 0, high = m;
        while (low < high) {
            int mid = low + high + 1 >> 1;
            int cur = mid;
            int[] c = new int[31];
            for (int i = 0; i < 30; i++) {
                if (b[i] <= cur) {
                    c[i] = b[i];
                    cur -= b[i];
                } else {
                    c[i] = cur;
                    break;
                }
            }

            for (int i = 0; i < 30; i++) {
                int d = a[i] > c[i] ? c[i] : a[i];
                c[i] -= d;
                c[i + 1] += c[i] + 1 >> 1;
            }

            if (c[30] == 0) {
                low = mid;
            } else {
                high = mid - 1;
            }
        }
        printf(low);
    }

    void printf() {
        out.print(answer);
    }

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

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

    void printf(Stream<?> str) {
        str.forEach(o -> add(o, " "));
        add("\n");
    }

    void printf(Object... obj) {
        printf(false, obj);
    }

    void printfWithDescription(Object... obj) {
        printf(true, obj);
    }

    private void printf(boolean b, Object... obj) {

        if (obj.length > 1) {
            for (int i = 0; i < obj.length; i++) {
                if (b) add(obj[i].getClass().getSimpleName(), " - ");
                if (obj[i] instanceof Collection<?>) {
                    printf((Collection<?>) obj[i]);
                } else if (obj[i] instanceof int[][]) {
                    printf((int[][]) obj[i]);
                } else if (obj[i] instanceof long[][]) {
                    printf((long[][]) obj[i]);
                } else if (obj[i] instanceof double[][]) {
                    printf((double[][]) obj[i]);
                } else printf(obj[i]);
            }
            return;
        }

        if (b) add(obj[0].getClass().getSimpleName(), " - ");
        printf(obj[0]);
    }

    void printf(Object o) {
        if (o instanceof int[])
            printf(Arrays.stream((int[]) o).boxed());
        else if (o instanceof char[])
            printf(new String((char[]) o));
        else if (o instanceof long[])
            printf(Arrays.stream((long[]) o).boxed());
        else if (o instanceof double[])
            printf(Arrays.stream((double[]) o).boxed());
        else if (o instanceof boolean[]) {
            for (boolean b : (boolean[]) o) add(b, " ");
            add("\n");
        } else
            add(o, "\n");
    }

    void printf(int[]... obj) {
        for (int i = 0; i < obj.length; i++) printf(obj[i]);
    }

    void printf(long[]... obj) {
        for (int i = 0; i < obj.length; i++) printf(obj[i]);
    }

    void printf(double[]... obj) {
        for (int i = 0; i < obj.length; i++) printf(obj[i]);
    }

    void printf(boolean[]... obj) {
        for (int i = 0; i < obj.length; i++) printf(obj[i]);
    }

    void printf(Collection<?> col) {
        printf(col.stream());
    }

    <T, K> void add(T t, K k) {
        if (t instanceof Collection<?>) {
            ((Collection<?>) t).forEach(i -> add(i, " "));
        } else if (t instanceof Object[]) {
            Arrays.stream((Object[]) t).forEach(i -> add(i, " "));
        } else
            add(t);
        add(k);
    }

    <T> void add(T t) {
        answer.append(t);
    }

    static class Reader {
        private BufferedReader br;
        private StringTokenizer st;

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

        Reader(String fileName) throws FileNotFoundException {
            br = new BufferedReader(new FileReader(fileName));
        }

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

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

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

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

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

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

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

public class C {
	private static BufferedReader in;

	public void run() throws IOException {
		StringTokenizer st = new StringTokenizer(in.readLine());
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		st = new StringTokenizer(in.readLine());
		int[] a = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = Integer.parseInt(st.nextToken());
		}
		st = new StringTokenizer(in.readLine());
		int[] b = new int[m];
		for (int i = 0; i < m; i++) {
			b[i] = Integer.parseInt(st.nextToken());
		}
		Arrays.sort(a);
		Arrays.sort(b);
		int[] f = new int[31];
		for (int i = 0; i < n; i++) {
			int ai = a[i];
			for (int t = 0; t <= 30; t++) {
				if (((ai >> t) & 1) == 1) {
					f[t]++;
				}
			}
		}
		int lo = 0;
		int hi = m + 1;
		while (lo + 1 < hi) {
			int mid = (lo + hi) / 2;
			int[] d = new int[32];
			for (int i = 0; i < mid; i++) {
				d[b[i]]++;
			}
			for (int t = 0; t <= 30; t++) {
				d[t] -= f[t];
				if (d[t] > 0) {
					d[t + 1] += (d[t] + 1) / 2;
				}
			}
			if (d[31] > 0) {
				hi = mid;
			} else {
				lo = mid;
			}
		}
		System.out.println(lo);
	}

	public static void main(String[] args) throws IOException {
		Locale.setDefault(Locale.US);
		in = new BufferedReader(new InputStreamReader(System.in));
		new C().run();
		in.close();
	}
}

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

public class C309 {

	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner(System.in);
		PrintWriter pw = new PrintWriter(System.out);
		int n = sc.nextInt();
		int m = sc.nextInt();
		int nn = n;
		int mm = m;
		int[] cntspace = new int[32];
		int[] cntarrays = new int[32];
		while (n-- > 0) {
			int mult = 0;
			int x = sc.nextInt();
			while (mult < 32) {
				if ((x & (1 << mult)) != 0) {
					cntspace[mult]++;
				}
				mult++;

			}
		}
		while (m-- > 0) {
			cntarrays[sc.nextInt()]++;
		}

		int[] space3 = new int[nn * 31];
		int[] arrays3 = new int[mm + 1];
//		Queue<Integer> space2 = new LinkedList<Integer>();
//		Queue<Integer> arrays2 = new LinkedList<Integer>();
		int adx = 0;
		int sdx = 0;
		int asize = 0;
		int ssize = 0;
		for (int i = 0; i < 32; i++) {
			while (cntspace[i]-- > 0)
				space3[ssize++] = (1 << i);
			while (cntarrays[i]-- > 0)
				arrays3[asize++] = (1 << i);

		}
		int ans = 0;
		while (adx < asize) {
			int cur = arrays3[adx++];
			while (sdx < ssize && space3[sdx] < cur)
				sdx++;
			if (sdx == ssize)
				break;
			int h = space3[sdx++];
			while (true) {
				h -= cur;
				ans++;
				if (adx != asize && h >= arrays3[adx])
					cur = arrays3[adx++];
				else
					break;
			}
//			int mult = 1;
//			while (h > 0) {
//				if (h % 2 == 1)
//					space.add(mult);
//				mult <<= 1;
//				h >>= 1;
//			}
		}
		pw.println(ans);
		pw.close();
	}

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

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

		public Scanner(FileReader r) {
			br = new BufferedReader(r);
		}

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

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

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

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

		public double nextDouble() throws IOException {
			String x = next();
			StringBuilder sb = new StringBuilder("0");
			double res = 0, f = 1;
			boolean dec = false, neg = false;
			int start = 0;
			if (x.charAt(0) == '-') {
				neg = true;
				start++;
			}
			for (int i = start; i < x.length(); i++)
				if (x.charAt(i) == '.') {
					res = Long.parseLong(sb.toString());
					sb = new StringBuilder("0");
					dec = true;
				} else {
					sb.append(x.charAt(i));
					if (dec)
						f *= 10;
				}
			res += Long.parseLong(sb.toString()) / f;
			return res * (neg ? -1 : 1);
		}

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

	}
}

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

public class Main {

	static class FastScanner {
		BufferedReader s;
		StringTokenizer st;

		public FastScanner(InputStream InputStream) {
			st = new StringTokenizer("");
			s = new BufferedReader(new InputStreamReader(InputStream));
		}

		public FastScanner(File f) throws FileNotFoundException {
			st = new StringTokenizer("");
			s = new BufferedReader(new FileReader(f));
		}

		public int nextInt() throws IOException {
			if (st.hasMoreTokens())
				return Integer.parseInt(st.nextToken());
			else {
				st = new StringTokenizer(s.readLine());
				return nextInt();
			}
		}

		public BigInteger big() throws IOException {
			if (st.hasMoreTokens())
				return new BigInteger(st.nextToken());
			else {
				st = new StringTokenizer(s.readLine());
				return big();
			}
		}

		public double nextDouble() throws IOException {
			if (st.hasMoreTokens())
				return Double.parseDouble(st.nextToken());
			else {
				st = new StringTokenizer(s.readLine());
				return nextDouble();
			}
		}

		public long nextLong() throws IOException {
			if (st.hasMoreTokens())
				return Long.parseLong(st.nextToken());
			else {
				st = new StringTokenizer(s.readLine());
				return nextLong();
			}
		}

		public String next() throws IOException {
			if (st.hasMoreTokens())
				return st.nextToken();
			else {
				st = new StringTokenizer(s.readLine());
				return next();
			}

		}

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

		public void close() throws IOException {
			s.close();
		}

	}

	public static void main(String[] args) throws IOException {
		FastScanner in = new FastScanner(System.in);
		int n = in.nextInt(), m = in.nextInt();
		int[] bits= new int[32];
		for(int x = 0; x < n; x++) {
			int  val = in.nextInt();
			for(int i = 0; i < 32; i++) {
				int mask = (1<<i);
				if((val & mask) != 0)
					bits[i]++;
			}
 		}
		ArrayList<Integer> arr = new ArrayList<Integer>();
		for(int x = 0; x < m; x++)
			arr.add(in.nextInt());
		Collections.sort(arr);
		int ans = 0, high = 31;
		for(int x = 0; x < m; x++) {
			int val = arr.get(x);
			if(bits[val] > 0) {
				bits[val]--;
				ans++;
			}
			else {
				high = val + 1;
				while(high < 32 && bits[high] == 0) high++;
				if(high < 32) {
					bits[high]--;
					ans++;
					for(int i = val; i < high; i++)
						bits[i]++;
				}
			}
		}
		System.out.println(ans);
	}

}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

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

    static class CMemoryForArrays {
        private InputReader in;
        private PrintWriter out;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            this.in = in;
            this.out = out;
            int n = in.nextInt();
            int m = in.nextInt();
            int[] a = in.nextIntArray(n, 1);
            int[] b = in.nextIntArray(m, 1);
            int[] cnt = new int[31];
            QuickSort.sort(b, 1, m);
            for (int i = 1; i <= n; i++) {
                for (int j = 0; j <= 30; j++) {
                    if (((a[i] >> j) & 1) == 1) {
                        cnt[j]++;
                    }
                }
            }
//        for (int i = 0; i <= 2; i++) {
//            out.print(cnt[i] + " ");
//        }
//        out.println();
            int cur = 0;
            int ans = 0;
            for (int i = 1; i <= m; i++) {
                while (cnt[cur] == 0 || b[i] > cur) {
                    cur++;
                    if (cur == 31) {
                        out.println(ans);
                        return;
                    }
                }
                ans++;
                cnt[cur]--;
                while (cur >= b[i] && cur != 0) {
                    cur--;
                    cnt[cur]++;
                }
            }
            out.println(ans);
        }

    }

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

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

        public int read() {
            if (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 int[] nextIntArray(int length, int stIndex) {
            int[] arr = new int[length + stIndex];
            for (int i = stIndex; i < stIndex + length; i++)
                arr[i] = nextInt();
            return arr;
        }

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

    }

    static class QuickSort {
        public static void sort(int[] list, int lowIndex, int highIndex) {
            ArrayAlgorithm.shuffleArray(list, lowIndex, highIndex);
            Arrays.sort(list, lowIndex, highIndex + 1);
        }

    }

    static class OneNumberGen {
        private static long genI(long min, long max) {
            return ThreadLocalRandom.current().nextLong(min, max + 1);
        }

        public static long genInt(long min, long max) {
            if (min >= 0)
                return (genI(min, max));
            else if (max >= 0) {
                double ratio = (double) Math.abs(min) / (Math.abs(min) + max);
                ratio *= 1000000000000000000D;
                double prob = (double) (OneNumberGen.genInt(1, 1000000000000000000L));
                if (Double.compare(ratio, prob) > 0) {
                    return -(genI(0, -min));
                } else {
                    return (genI(0, max));
                }
            } else
                return -(OneNumberGen.genI(-min, -max));
        }

    }

    static class ArrayAlgorithm {
        public static void shuffleArray(int[] array, int stIndex, int enIndex) {
            for (int i = enIndex; i > stIndex; i--) {
                int index = (int) OneNumberGen.genInt(stIndex, i - 1);
                if (index != i) {
                    array[index] ^= array[i];
                    array[i] ^= array[index];
                    array[index] ^= array[i];
                }
            }
        }

    }
}

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

public class TestGenerator {
    static final int mod = 998244353;

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        PrintWriter wr = new PrintWriter(System.out);

        int n = sc.nextInt();
        int m = sc.nextInt();
        int[] a = new int[32];
        int[] b = new int[32];
        for (int i = 0; i < n; i++) {
            int x = sc.nextInt();
            for (int j = 0; j < 32 && x > 0; j++, x >>= 1)
                if((x&1) == 1)
                    a[j]++;
        }
        for (int i = 0; i < m; i++) {
            b[sc.nextInt()]++;
        }
        int ans = 0;
        for (int i = 0; i < 32; i++) {
            long x = a[i] * (1l << i);
            for (int j = 0; j <= i; j++) {
                long min = Math.min(x >> j, b[j]);
                b[j] -= min;
                ans += min;
                x -= min << j;
            }
        }
        wr.println(ans);

        wr.close();
    }

    static int[] RandomizeArray(int[] array){
        Random rgen = new Random();  // Random number generator

        for (int i=0; i<array.length; i++) {
            int randomPosition = rgen.nextInt(array.length);
            int temp = array[i];
            array[i] = array[randomPosition];
            array[randomPosition] = temp;
        }

        return array;
    }
}

class Scanner
{
    StringTokenizer st;
    BufferedReader br;

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

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

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

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

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

    public double nextDouble() throws IOException
    {
        String x = next();
        StringBuilder sb = new StringBuilder("0");
        double res = 0, f = 1;
        boolean dec = false, neg = false;
        int start = 0;
        if(x.charAt(0) == '-')
        {
            neg = true;
            start++;
        }
        for(int i = start; i < x.length(); i++)
            if(x.charAt(i) == '.')
            {
                res = Long.parseLong(sb.toString());
                sb = new StringBuilder("0");
                dec = true;
            }
            else
            {
                sb.append(x.charAt(i));
                if(dec)
                    f *= 10;
            }
        res += Long.parseLong(sb.toString()) / f;
        return res * (neg?-1:1);
    }

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

}

import java.util.*;
import java.io.*;
import static java.lang.Long.min;
import static java.lang.Long.max;
import static java.lang.Math.abs;
import static java.lang.Math.pow;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
    public class Mamo {
static Reader  in=new Reader ();
static long ans,sum,mx=(long) pow(10,9);
static int []a,b;
static StringBuilder sd=new StringBuilder();
    public static void main(String [] args) {
       int n=in.nextInt(),m=in.nextInt();
       a=new int [31];b=new int [31];
       int w[]=new int [31];
       w[0]=1;
       for(int i=1;i<=30;i++)w[i]=w[i-1]*2;
       for(int i=0;i<n;i++){
       int x=in.nextInt();
       while(x!=0)
       for(int u=0;u<31;u++)
       if(w[u]>x){
       x-=w[u-1];a[u-1]++;break;}
       }

       for(int i=0;i<m;i++){
       int x=in.nextInt();
       if(x<30)b[x]++;
       }

   for(int i=0,u=0;i<=30&&u<=30;){
   while(i!=31&&a[i]==0)i++;
   while(u!=31&&b[u]==0)u++;
   if(i==31||u==31)break;
   if(i==u){int x=a[i];
   ans+=min(a[i],b[u]);
   a[i]=0;
   b[u]=(int) max(0,b[u]-x);
   }
   else if(i<u) {i++;}
   else if(i>u){
   int x=i-u;
   x=(int) pow(2,x);
   while(b[u]>0&&a[i]>0){
       ans+=min(b[u],x);
       b[u]-=x;a[i]--;
       if(b[u]<0){
           x=b[u]*-1;
           b[u]=0;

           for(;u<31;u++){
           if(b[u]>0){
           int o=x;
           ans+=min(x,b[u]);
           x=(int) max(x-b[u],0);
           b[u]=(int) max(0,b[u]-o);
           }
           if(x<2){u=0;break;}
           x/=2;
           }
           }
   }}
   }System.out.println(ans);
    }
   static long gcd(long a,long b){
       if(b==0){return a;}
   return gcd(b,a%b);}
   static class Reader
    {
        private InputStream mIs;private byte[] buf = new byte[1024];private int curChar,numChars;public Reader() { this(System.in); }public Reader(InputStream is) { mIs = is;}
        public int read() {if (numChars == -1) throw new InputMismatchException();if (curChar >= numChars) {curChar = 0;try { numChars = mIs.read(buf);} catch (IOException e) { throw new InputMismatchException();}if (numChars <= 0) return -1; }return buf[curChar++];}
        public String nextLine(){int c = read();while (isSpaceChar(c)) c = read();StringBuilder res = new StringBuilder();do {res.appendCodePoint(c);c = read();}while (!isEndOfLine(c));return res.toString() ;}
        public String s(){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 long l(){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 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 double d() throws IOException {return Double.parseDouble(s()) ;}
        public boolean isSpaceChar(int c) { return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1; }
        public boolean isEndOfLine(int c) { return c == '\n' || c == '\r' || c == -1; }
        public int[] arr(int n){int[] ret = new int[n];for (int i = 0; i < n; i++) {ret[i] = nextInt();}return ret;}
    }

}

class Sorting{

 public static int[] bucketSort(int[] array, int bucketCount) {

 if (bucketCount <= 0) throw new IllegalArgumentException("Invalid bucket count");

 if (array.length <= 1) return array; //trivially sorted

 int high = array[0];

 int low = array[0];

 for (int i = 1; i < array.length; i++) { //find the range of input elements

 if (array[i] > high) high = array[i];

 if (array[i] < low) low = array[i];

 }

 double interval = ((double)(high - low + 1))/bucketCount; //range of one bucket

 ArrayList<Integer> buckets[] = new ArrayList[bucketCount];

 for (int i = 0; i < bucketCount; i++) { //initialize buckets

 buckets[i] = new ArrayList();

 }

 for (int i = 0; i < array.length; i++) { //partition the input array

 buckets[(int)((array[i] - low)/interval)].add(array[i]);

 }

 int pointer = 0;

 for (int i = 0; i < buckets.length; i++) {

 Collections.sort(buckets[i]); //mergeSort

 for (int j = 0; j < buckets[i].size(); j++) { //merge the buckets

 array[pointer] = buckets[i].get(j);

 pointer++;

 }

}

return array;

}

}

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

public class Main {

    public static void main(String[] args) throws Exception {
        IO io ;
        try {
            io = new IO("in.in", null);
        } catch (IOException e) {
            io = new IO(null, null);
        }

        int n = io.getNextInt(),m = io.getNextInt();
        int [] need = new int[32];
        int [] have = new int[32];
        for (int i = 0;i < n;i++){
            int x = io.getNextInt();
            for (int j = 0;j < 32 && x > 0;j++,x >>= 1)
                if ((x & 1) == 1)
                    have[j]++;
        }
        for (int i = 0;i < m;i++)
            need[io.getNextInt()]++;

        int ans = 0;
        for (int i = 0;i < 32;i++) {
            long r = (1L << i)*have[i];
            for (int j = 0; j <= i; j++) {
                long d = r >> j;
                d = Math.min(d, need[j]);
                ans += d;
                need[j] -= d;
                r -= d << j;
            }
        }
        io.println(ans);
        io.close();
    }
    private static final int onebillion7 = 1000000007;
}

class IO{
    private BufferedReader br;
    private StringTokenizer st;
    private PrintWriter writer;
    private String inputFile,outputFile;

    public boolean hasMore() throws IOException{
        if(st != null && st.hasMoreTokens()) return true;
        if(br != null && br.ready()) return true;
        return false;
    }

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

    public String getNextLine() throws FileNotFoundException, IOException{
        return br.readLine().trim();
    }

    public int getNextInt() throws FileNotFoundException, IOException{
        return Integer.parseInt(getNext());
    }
    public long getNextLong() throws FileNotFoundException, IOException{
        return Long.parseLong(getNext());
    }

    public void print(double x,int num_digits) throws  IOException{
        writer.printf("%." + num_digits + "f" ,x);
    }
    public void println(double x,int num_digits) throws  IOException{
        writer.printf("%." + num_digits + "f\n" ,x);
    }
    public void print(Object o) throws  IOException{
        writer.print(o.toString());
    }

    public void println(Object o) throws  IOException{
        writer.println(o.toString());
    }
    public IO(String x,String y) throws FileNotFoundException, IOException{
        inputFile = x;
        outputFile = y;
        if(x != null) br = new BufferedReader(new FileReader(inputFile));
        else br = new BufferedReader(new InputStreamReader(System.in));
        if(y != null) writer = new PrintWriter(new BufferedWriter(new FileWriter(outputFile)));
        else writer = new PrintWriter(new OutputStreamWriter(System.out));
    }

    protected void close() throws IOException{
        br.close();
        writer.close();
    }
    public void outputArr(Object [] A) throws IOException{
        int L = A.length;
        for (int i = 0;i < L;i++) {
            if(i > 0) writer.print(" ");
            writer.print(A[i]);
        }
        writer.print("\n");
    }
}

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

public class C {
	BufferedReader reader;
    StringTokenizer tokenizer;
    PrintWriter out;

    public void shuffleArray(int[] arr) {
        Random rnd = new Random();
        for (int i = arr.length - 1; i >= 0; i--) {
            int pos = rnd.nextInt(i + 1);
            int temp = arr[i];
            arr[i] = arr[pos];
            arr[pos] = temp;
        }
    }
	public void solve() throws IOException {
		int max_bit = 30;

		int N = nextInt();
		int M = nextInt();

		int[] space = new int[max_bit+1];
		int[] size = new int[max_bit+1];
		for(int i = 0; i < N; i++){
			int a = nextInt();
			for(int b = 0; b <= max_bit; b++){
				if( (a >> b & 1) == 1 )
					space[b]++;
			}
		}
		for(int i = 0; i < M; i++)
			size[ nextInt() ]++;

		int ans = 0;
		int cur_space = 0;
		int cur_can = space[cur_space];
		outer: for(int i = 0; i <= max_bit; i++){
			while( size[i] > cur_can ){
				size[i] -= cur_can;
				ans += cur_can;

				cur_space++;
				if( cur_space > max_bit ) break outer;

				cur_can = space[cur_space] * (int)Math.pow(2, cur_space-i);
			}

			cur_can -= size[i];
			ans += size[i];

			if( cur_space > i)
				cur_can /= 2;
			else
				cur_can = 0;
		}
		out.println(ans);
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new C().run();
	}

	public void run() {
        try {
            reader = new BufferedReader(new InputStreamReader(System.in));
            tokenizer = null;
            out = new PrintWriter(System.out);
            solve();
            reader.close();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

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

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

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

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

}

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

public class CF {
    FastScanner in;
    PrintWriter out;

    boolean canFit(int[] a, int[] b, int fr, int max) {
        if (fr == max) {
            return true;
        } else {
            int nextVal = 1 << b[fr];
            for (int i = 0; i < a.length; i++) {
                if (a[i] >= nextVal) {
                    a[i] -= nextVal;
                    if (canFit(a, b, fr + 1, max)) {
                        a[i] += nextVal;
                        return true;
                    }
                    a[i] += nextVal;
                }
            }
        }
        return false;
    }

    int stupid(int[] a, int[] b) {
        Arrays.sort(b);
        int l = 0, r = b.length + 1;
        while (r - l > 1) {
            int m = (l + r) / 2;
            if (canFit(a, b, 0, m)) {
                l = m;
            } else {
                r = m;
            }
        }
        return l;
    }

    int MAX = 31;

    boolean can(int[] ask, int[] have) {
        int[] ask2 = new int[MAX + 1];
        for (int i = 0; i < MAX; i++) {
            ask2[i] = ask[i];
        }
        for (int i = 0; i < MAX; i++) {
            int cc = Math.min(ask2[i], have[i]);
            ask2[i] -= cc;
            if (ask2[i] != 0) {
                ask2[i + 1] += 1 + (ask2[i] - 1) / 2;
            }
        }
        return ask2[ask2.length - 1] == 0;
    }

    int solve2(int[] a, int[] b) {
        int n = a.length;
        int m = b.length;
        int[] ask = new int[MAX];
        for (int i = 0; i < m; i++) {
            ask[b[i]]++;
        }
        int[] have = new int[MAX];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < MAX; j++) {
                if (((1 << j) & a[i]) != 0) {
                    have[j]++;
                }
            }
        }
        int l = 0, r = m + 1;
        while (r - l > 1) {
            int med = (l + r) / 2;
            int[] askMed = new int[MAX];
            int alr = 0;
            for (int i = 0; i < MAX; i++) {
                askMed[i] = Math.min(med - alr, ask[i]);
                alr += askMed[i];
            }
            if (can(askMed, have)) {
                l = med;
            } else {
                r = med;
            }
        }
        return l;
    }

    void solve() {
        int n = in.nextInt();
        int m = in.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = in.nextInt();
        }
        int[] b = new int[m];
        for (int i = 0; i < m; i++) {
            b[i] = in.nextInt();
        }
        out.println(solve2(a, b));
    }

    Random rnd = new Random(123);

    void solve1() {
        for (int test = 0;; test++) {
            System.err.println(test);
            int n = 1 + rnd.nextInt(10);
            int m = 1 + rnd.nextInt(10);
            int[] a = new int[n];
            for (int i = 0; i < n; i++) {
                a[i] = rnd.nextInt(100);
            }
            int[] b = new int[m];
            for (int i = 0; i < m; i++) {
                b[i] = rnd.nextInt(7);
            }
            int v2 = solve2(a, b);
            int v1 = stupid(a, b);
            System.err.println(v1 + " " + v2);
            if (v1 != v2) {
                System.err.println(Arrays.toString(a));
                System.err.println(Arrays.toString(b));
                solve2(a, b);
                throw new AssertionError();
            }
        }
    }

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

            solve();

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

    void runIO() {

        in = new FastScanner(System.in);
        out = new PrintWriter(System.out);

        solve();

        out.close();
    }

    class FastScanner {
        BufferedReader br;
        StringTokenizer st;

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

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

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

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

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

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

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

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

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

	void solve()
	{
		int n = ni(), m = ni();
		int[] a = na(n);

		a = radixSort(a);

		int[] b = na(m);
		int[] bf = new int[32];
		for(int v : b){
			bf[v]++;
		}
		int ct = 0;
		for(int j = 0;j < 31;j++){
			for(int i = 0;i < n;i++){
				if(bf[j] > 0 && a[i]<<31-j<0){
					bf[j]--;
					ct++;
					a[i] -= 1<<j;
				}
			}
			for(int i = 0;i < n;i++){
				if(bf[j] > 0){
					int ref = Math.min(bf[j], a[i]>>>j);
					bf[j] -= ref;
					ct += ref;
					a[i] -= ref<<j;
				}
			}
		}
		out.println(ct);
	}

	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;
	}

	void run() throws Exception
	{
//		int n = 1000000, m = 1000000;
//		Random gen = new Random();
//		StringBuilder sb = new StringBuilder();
//		sb.append(n + " ");
//		sb.append(m + " ");
//		for(int i = 0;i < n;i++){
//			sb.append(gen.nextInt(1000000000) + " ");
//		}
//		for(int i = 0;i < m;i++){
//			sb.append(gen.nextInt(31) + " ");
//		}
//		INPUT = sb.toString();

		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

import static java.util.Collections.*;
import static java.lang.Math.*;
import static java.util.Arrays.*;
import static java.math.BigInteger.*;
import static java.lang.Character.*;

public class Main {

    void run(){
//        boolean oj = true;
//        boolean oj = false;

        Locale.setDefault(Locale.US);
        boolean oj = System.getProperty("ONLINE_JUDGE")!=null;

        String fileName = oj? "castle" : "dwarf";
        try {
            if( oj ){
                br = new BufferedReader(new InputStreamReader(System.in));
                out = new PrintWriter(new OutputStreamWriter(System.out));
            }
            else{
                br  = new BufferedReader(new FileReader(fileName+".in" ));
                out = new PrintWriter   (new FileWriter(fileName+".out"));
            }
        } catch (Exception e) {
            MLE();
        }
        long tb = System.currentTimeMillis();
        solve();
//        if( !oj )
//            out.println("TIME: " + (System.currentTimeMillis() - tb) / 1e3) ;
        exit(0);
    }

    BufferedReader br;
    StringTokenizer st;
    PrintWriter out;

    String next(){
        while( st==null || !st.hasMoreElements() ){
            try {
                st = new StringTokenizer(br.readLine());
            } catch (IOException e) {
                return null;
            }
        }
        return st.nextToken();
    }
    String nextLine(){
        try {
            return br.readLine();
        } catch (Exception e) {
            return null;
        }
    }
    int nextInt(){ return Integer.parseInt(next()); }
    double nextDouble(){ return Double.parseDouble(next()); }
    long nextLong(){ return Long.parseLong(next()); }

    void exit( int val ){
        out.flush();
        System.exit(val);
    }

    void MLE(){
        int[][] arr = new int[1024*1024][];
        for( int i = 0; i < 1024*1024; ++i )
            arr[i] = new int[1024*1024];
    }

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

    class MultiTreeSet<Key>{
        TreeMap<Key,Integer> tm;

        MultiTreeSet(){
            tm = new TreeMap<>();
        }

        void add( Key key ){
            if( !tm.containsKey(key) )
                tm.put( key, 1 );
            else
                tm.put( key, 1 + tm.get(key) );
        }

        boolean isEmpty(){
            return tm.isEmpty();
        }

        Key pollLast(){
            if( tm.isEmpty() )
                return null;
            Key ans = tm.lastKey();
            tm.put( ans, tm.get(ans) - 1 );
            if( tm.get(ans) == 0 ) tm.remove(ans);
            return ans;
        }

    }

    final int maxCnt = 50;
    int n, m;
    int szArr;
    int[] arr;
    MultiTreeSet<Integer>[] cnt;

    boolean isOdd( int v ){ return (v&1)==1; }

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

        szArr = n;
        arr = new int[n];
        for( int i = 0; i < n; ++i )
            arr[i] = nextInt();

        cnt = new MultiTreeSet[maxCnt+1];
        for( int i = 0; i < cnt.length; ++i ) cnt[i] = new MultiTreeSet<>();
        for( int i = 0; i < m; ++i )
            cnt[nextInt()].add(1);

        int[] odd  = new int[n],
               even = new int[n];
        int szOdd, szEven;
        int ans = 0;
        for( int pos = 0; pos <= 31; ++pos ){
            szOdd = szEven = 0;
            for( int i = 0; i < n; ++i ){
                if( isOdd(arr[i]) )
                    odd[szOdd++] = arr[i];
                else
                    even[szEven++] = arr[i];
            }
            while( 0 < szOdd && !cnt[pos].isEmpty() ){
                even[szEven++] = odd[--szOdd] - 1;
                ans += cnt[pos].pollLast();
            }
            while( !cnt[pos].isEmpty() ){
                Integer a = cnt[pos].pollLast();
                Integer b = cnt[pos].pollLast();
                if( b == null ) b = 0;
                cnt[pos+1].add( a + b );
            }
            szArr = 0;
            for( int i = 0; i < szOdd ; ++i ) arr[szArr++] = odd [i]>>1;
            for( int i = 0; i < szEven; ++i ) arr[szArr++] = even[i]>>1;
            if( szArr != n ) MLE();
        }
        out.println(ans);
    }

    void deb(){
    }

}

import java.io.StreamTokenizer;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.util.ArrayDeque;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.Queue;
import java.util.Collection;
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;
		TokenizerReader in = new TokenizerReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskC solver = new TaskC();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskC {
    public void solve(@SuppressWarnings("UnusedParameters") int testNumber, TokenizerReader in, PrintWriter out) {
        int n = in.nextInt(), m = in.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; ++i)
            a[i] = in.nextInt();
        int[] cnt = new int[31];
        for (int i = 0; i < m; ++i)
            cnt[in.nextInt()]++;
        Queue<Integer> q = new ArrayDeque<Integer>(m);
        int result = 0;
        for (int b = 0; b <= 29; ++b) {
            for (int i = 0; i < cnt[b]; ++i)
                q.add(1);
            for (int i = 0; i < n && !q.isEmpty(); ++i) {
                if ((a[i] & (1<<b)) > 0)
                    result += q.remove();
            }
            int s = q.size();
            int i;
            for (i = 0; i+1 < s; i += 2)
                q.add(q.remove() + q.remove());
            if (i < s)
                q.add(q.remove());
        }
        out.println(result);
    }
}

class TokenizerReader extends StreamTokenizer {
    public TokenizerReader(InputStream in) {
        super(new BufferedReader(new InputStreamReader(in)));
        defaultConfig();
    }

    public String nextString() {
        try {
            nextToken();
        } catch (IOException e) {
            throw new RuntimeException("nextString: exception in line " + lineno(), e);
        }
        return sval;
    }

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

    public void defaultConfig() {
        resetSyntax();
        wordChars(33, 126);
        whitespaceChars(0, ' ');
    }

    }

import java.io.StreamTokenizer;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Reader;
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;
		TokenizerReader in = new TokenizerReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskC solver = new TaskC();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskC {
    public void solve(@SuppressWarnings("UnusedParameters") int testNumber, TokenizerReader in, PrintWriter out) {
        int n = in.nextInt(), m = in.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; ++i)
            a[i] = in.nextInt();
        ArrayList<Integer>[] e = new ArrayList[32];
        for (int i = 0; i < 32; ++i)
            e[i] = new ArrayList<Integer>();
        for (int i = 0; i < m; ++i)
            e[in.nextInt()].add(1);
        int result = 0;
        for (int b = 0; b <= 29; ++b) {
            for (int i = 0; i < n; ++i) {
                if ((a[i] % 2) == 1 && !e[b].isEmpty()) {
                    result += e[b].get(e[b].size() - 1);
                    e[b].remove(e[b].size() - 1);
                }
                a[i] /= 2;
            }
            int s = e[b].size() % 2;
            if (s == 1)
                e[b+1].add(e[b].get(0));
            while (s < e[b].size()) {
                e[b+1].add(e[b].get(s) + e[b].get(s+1));
                s += 2;
            }
            e[b].clear();
        }
        out.println(result);
    }
}

class TokenizerReader extends StreamTokenizer {
    public TokenizerReader(InputStream in) {
        super(new BufferedReader(new InputStreamReader(in)));
        defaultConfig();
    }

    public String nextString() {
        try {
            nextToken();
        } catch (IOException e) {
            throw new RuntimeException("nextString: exception in line " + lineno(), e);
        }
        return sval;
    }

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

    public void defaultConfig() {
        resetSyntax();
        wordChars(33, 126);
        whitespaceChars(0, ' ');
    }

    }

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

import static java.util.Collections.*;
import static java.lang.Math.*;
import static java.util.Arrays.*;
import static java.math.BigInteger.*;
import static java.lang.Character.*;

public class Main {

    void run(){
//        boolean oj = true;
//        boolean oj = false;

        Locale.setDefault(Locale.US);
        boolean oj = System.getProperty("ONLINE_JUDGE")!=null;

        String fileName = oj? "castle" : "dwarf";
        try {
            if( oj ){
                br = new BufferedReader(new InputStreamReader(System.in));
                out = new PrintWriter(new OutputStreamWriter(System.out));
            }
            else{
                br  = new BufferedReader(new FileReader(fileName+".in" ));
                out = new PrintWriter   (new FileWriter(fileName+".out"));
            }
        } catch (Exception e) {
            MLE();
        }
        long tb = System.currentTimeMillis();
        solve();
//        if( !oj )
//            out.println("TIME: " + (System.currentTimeMillis() - tb) / 1e3) ;
        exit(0);
    }

    BufferedReader br;
    StringTokenizer st;
    PrintWriter out;

    String next(){
        while( st==null || !st.hasMoreElements() ){
            try {
                st = new StringTokenizer(br.readLine());
            } catch (IOException e) {
                return null;
            }
        }
        return st.nextToken();
    }
    String nextLine(){
        try {
            return br.readLine();
        } catch (Exception e) {
            return null;
        }
    }
    int nextInt(){ return Integer.parseInt(next()); }
    double nextDouble(){ return Double.parseDouble(next()); }
    long nextLong(){ return Long.parseLong(next()); }

    void exit( int val ){
        out.flush();
        System.exit(val);
    }

    void MLE(){
        int[][] arr = new int[1024*1024][];
        for( int i = 0; i < 1024*1024; ++i )
            arr[i] = new int[1024*1024];
    }

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

    final int maxCnt = 50;
    int n, m;
    int szArr;
    int[] arr;
    Stack<Integer>[] cnt;

    boolean isOdd( int v ){ return (v&1)==1; }

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

        szArr = n;
        arr = new int[n];
        for( int i = 0; i < n; ++i )
            arr[i] = nextInt();

        cnt = new Stack[maxCnt+1];
        for( int i = 0; i < cnt.length; ++i )
            cnt[i] = new Stack<>();
        for( int i = 0; i < m; ++i )
            cnt[nextInt()].add(1);

        int[] odd  = new int[n],
               even = new int[n];
        int szOdd, szEven;
        int ans = 0;
        for( int pos = 0; pos <= 31; ++pos ){
            szOdd = szEven = 0;
            for( int i = 0; i < n; ++i ){
                if( isOdd(arr[i]) )
                    odd[szOdd++] = arr[i];
                else
                    even[szEven++] = arr[i];
            }
            while( 0 < szOdd && !cnt[pos].isEmpty() ){
                even[szEven++] = odd[--szOdd] - 1;
                ans += cnt[pos].pop();
            }
            ArrayList<Integer> arrAdd = new ArrayList();
            while( !cnt[pos].isEmpty() ){
                Integer a = cnt[pos].pop();
                Integer b = cnt[pos].isEmpty()? 0 : cnt[pos].pop();
                arrAdd.add( a + b );
            }
            Collections.reverse(arrAdd);
            cnt[pos+1].addAll( arrAdd );
            szArr = 0;
            for( int i = 0; i < szOdd ; ++i ) arr[szArr++] = odd [i]>>1;
            for( int i = 0; i < szEven; ++i ) arr[szArr++] = even[i]>>1;
            if( szArr != n ) MLE();
        }
        out.println(ans);
    }

    void deb(){
    }

}

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

import static java.util.Collections.*;
import static java.lang.Math.*;
import static java.util.Arrays.*;
import static java.math.BigInteger.*;
import static java.lang.Character.*;

public class Main {

    void run(){
//        boolean oj = true;
//        boolean oj = false;

        Locale.setDefault(Locale.US);
        boolean oj = System.getProperty("ONLINE_JUDGE")!=null;

        String fileName = oj? "castle" : "dwarf";
        try {
            if( oj ){
                br = new BufferedReader(new InputStreamReader(System.in));
                out = new PrintWriter(new OutputStreamWriter(System.out));
            }
            else{
                br  = new BufferedReader(new FileReader(fileName+".in" ));
                out = new PrintWriter   (new FileWriter(fileName+".out"));
            }
        } catch (Exception e) {
            MLE();
        }
        long tb = System.currentTimeMillis();
        solve();
//        if( !oj )
//            out.println("TIME: " + (System.currentTimeMillis() - tb) / 1e3) ;
        exit(0);
    }

    BufferedReader br;
    StringTokenizer st;
    PrintWriter out;

    String next(){
        while( st==null || !st.hasMoreElements() ){
            try {
                st = new StringTokenizer(br.readLine());
            } catch (IOException e) {
                return null;
            }
        }
        return st.nextToken();
    }
    String nextLine(){
        try {
            return br.readLine();
        } catch (Exception e) {
            return null;
        }
    }
    int nextInt(){ return Integer.parseInt(next()); }
    double nextDouble(){ return Double.parseDouble(next()); }
    long nextLong(){ return Long.parseLong(next()); }

    void exit( int val ){
        out.flush();
        System.exit(val);
    }

    void MLE(){
        int[][] arr = new int[1024*1024][];
        for( int i = 0; i < 1024*1024; ++i )
            arr[i] = new int[1024*1024];
    }

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

    class MultiTreeSet<Key>{
        TreeMap<Key,Integer> tm;

        MultiTreeSet(){
            tm = new TreeMap<>();
        }

        void add( Key key ){
            if( !tm.containsKey(key) )
                tm.put( key, 1 );
            else
                tm.put( key, 1 + tm.get(key) );
        }

        boolean isEmpty(){
            return tm.isEmpty();
        }

        Key pollLast(){
            if( tm.isEmpty() )
                return null;
            Key ans = tm.lastKey();
            tm.put( ans, tm.get(ans) - 1 );
            if( tm.get(ans) == 0 ) tm.remove(ans);
            return ans;
        }

    }

    final int maxCnt = 50;
    int n, m;
    int szArr;
    int[] arr;
    MultiTreeSet<Integer>[] cnt;

    boolean isOdd( int v ){ return (v&1)==1; }

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

        szArr = n;
        arr = new int[n];
        for( int i = 0; i < n; ++i )
            arr[i] = nextInt();

        cnt = new MultiTreeSet[maxCnt+1];
        for( int i = 0; i < cnt.length; ++i ) cnt[i] = new MultiTreeSet<>();
        for( int i = 0; i < m; ++i )
            cnt[nextInt()].add(1);

        int[] odd  = new int[n],
               even = new int[n];
        int szOdd, szEven;
        int ans = 0;
        for( int pos = 0; pos <= 33; ++pos ){
            szOdd = szEven = 0;
            for( int i = 0; i < n; ++i ){
                if( isOdd(arr[i]) )
                    odd[szOdd++] = arr[i];
                else
                    even[szEven++] = arr[i];
            }
            while( 0 < szOdd && !cnt[pos].isEmpty() ){
                even[szEven++] = odd[--szOdd] - 1;
                ans += cnt[pos].pollLast();
            }
            while( !cnt[pos].isEmpty() ){
                Integer a = cnt[pos].pollLast();
                Integer b = cnt[pos].pollLast();
                if( b == null ) b = 0;
                cnt[pos+1].add( a + b );
            }
            szArr = 0;
            for( int i = 0; i < szOdd ; ++i ) arr[szArr++] = odd [i]>>1;
            for( int i = 0; i < szEven; ++i ) arr[szArr++] = even[i]>>1;
            if( szArr != n ) MLE();
        }
        out.println(ans);
    }

    void deb(){
    }

}

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

import static java.util.Collections.*;
import static java.lang.Math.*;
import static java.util.Arrays.*;
import static java.math.BigInteger.*;
import static java.lang.Character.*;

public class Main {

    void run(){
//        boolean oj = true;
//        boolean oj = false;

        Locale.setDefault(Locale.US);
        boolean oj = System.getProperty("ONLINE_JUDGE")!=null;

        String fileName = oj? "castle" : "dwarf";
        try {
            if( oj ){
                br = new BufferedReader(new InputStreamReader(System.in));
                out = new PrintWriter(new OutputStreamWriter(System.out));
            }
            else{
                br  = new BufferedReader(new FileReader(fileName+".in" ));
                out = new PrintWriter   (new FileWriter(fileName+".out"));
            }
        } catch (Exception e) {
            MLE();
        }
        long tb = System.currentTimeMillis();
        solve();
//        if( !oj )
//            out.println("TIME: " + (System.currentTimeMillis() - tb) / 1e3) ;
        exit(0);
    }

    BufferedReader br;
    StringTokenizer st;
    PrintWriter out;

    String next(){
        while( st==null || !st.hasMoreElements() ){
            try {
                st = new StringTokenizer(br.readLine());
            } catch (IOException e) {
                return null;
            }
        }
        return st.nextToken();
    }
    String nextLine(){
        try {
            return br.readLine();
        } catch (Exception e) {
            return null;
        }
    }
    int nextInt(){ return Integer.parseInt(next()); }
    double nextDouble(){ return Double.parseDouble(next()); }
    long nextLong(){ return Long.parseLong(next()); }

    void exit( int val ){
        out.flush();
        System.exit(val);
    }

    void MLE(){
        int[][] arr = new int[1024*1024][];
        for( int i = 0; i < 1024*1024; ++i )
            arr[i] = new int[1024*1024];
    }

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

    final int maxCnt = 50;
    int n, m;
    int szArr;
    int[] arr;
    ArrayList<Integer>[] cnt;

    boolean isOdd( int v ){ return (v&1)==1; }

    int pollLast( ArrayList<Integer> arr ){
        int val = arr.get(arr.size()-1);
        arr.remove( arr.size() - 1 );
        return val;
    }

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

        szArr = n;
        arr = new int[n];
        for( int i = 0; i < n; ++i )
            arr[i] = nextInt();

        cnt = new ArrayList[maxCnt+1];
        for( int i = 0; i < cnt.length; ++i )
            cnt[i] = new ArrayList<>();
        for( int i = 0; i < m; ++i )
            cnt[nextInt()].add(1);

        int[] odd  = new int[n],
               even = new int[n];
        int szOdd, szEven;
        int ans = 0;
        for( int pos = 0; pos <= 31; ++pos ){
            szOdd = szEven = 0;
            for( int i = 0; i < n; ++i ){
                if( isOdd(arr[i]) )
                    odd[szOdd++] = arr[i];
                else
                    even[szEven++] = arr[i];
            }
            while( 0 < szOdd && !cnt[pos].isEmpty() ){
                even[szEven++] = odd[--szOdd] - 1;
                ans += pollLast(cnt[pos]);
            }
            ArrayList<Integer> arrAdd = new ArrayList();
            while( !cnt[pos].isEmpty() ){
                Integer a = pollLast(cnt[pos]);
                Integer b = cnt[pos].isEmpty()? 0 : pollLast(cnt[pos]);
                arrAdd.add( a + b );
            }
            Collections.reverse(arrAdd);
            cnt[pos+1].addAll( arrAdd );
            szArr = 0;
            for( int i = 0; i < szOdd ; ++i ) arr[szArr++] = odd [i]>>1;
            for( int i = 0; i < szEven; ++i ) arr[szArr++] = even[i]>>1;
            if( szArr != n ) MLE();
        }
        out.println(ans);
    }

    void deb(){
    }

}

import java.io.*;

import static java.lang.Math.*;
import java.util.*;
import static java.util.Arrays.fill;
import static java.util.Arrays.sort;

public class Main {
	public static void main(String[] args) {
		if(new File("input.txt").exists())
			try {
				System.setIn(new FileInputStream("input.txt"));
			} catch (FileNotFoundException e1) {
				e1.printStackTrace();
			}
		new Thread(null, new Runnable() {
			public void run() {
				try {
					new Main().run();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}, "kek", 1 << 23).start();
	}

	BufferedReader in;
	PrintWriter out;
	StringTokenizer st = new StringTokenizer("");

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

	final int off = 31;
	int b[];
	int n, m;
	int step = 1000;

	long preA[] = new long[off];
	long preB[][];

	void solve() throws IOException{

		n = nextInt();
		m = nextInt();
		b = new int[m];
		int sz = m / step + 1;
		preB = new long[sz][off];

		for(int i = 0; i < n; i++){
			int x = nextInt();
			for(int k = 0; k < off; k++)
				if((x & (1 << k)) != 0)
					preA[k]++;
		}
		for(int i = 0; i < m; i++)
			b[i] = nextInt();
		sort(b);

		for(int i = 0; i < m; i++)
			preB[i / step][b[i]]++;
		for(int i = 1; i < sz; i++){
			for(int k = 0; k < off; k++)
				preB[i][k] += preB[i - 1][k];
		}
//		System.err.println(preB[0][29] + " " + preB[1][29]);
		int answer = 0;
		int le = 0;
		int ri = m;
		while (le <= ri) {
			int mid = (le + ri) >> 1;
			if (solve(mid)) {
				answer = max(answer, mid);
				le = mid + 1;
			} else {
				ri = mid - 1;
			}
		}
		out.println(answer);

	}
	boolean solve(int count){
		long cntA[] = new long[off];
		long cntB[] = new long[off];
		for(int k = 0; k < off; k++)
			cntA[k] = preA[k];
		int idx = count / step - 1;
		if(idx >= 0){
			for(int k = 0; k < 30; k++)
				cntB[k] += preB[idx][k];
		}
		int start = (count / step) * step;
//		System.err.println(count + " " + start + " | " + Arrays.toString(cntB));
		for(int i = start; i < count; i++){
			cntB[b[i]]++;
		}

		for(int k = off - 1; k > 0; k--){
			long z = min(cntA[k], cntB[k]);
			cntA[k] -= z;
			cntB[k] -= z;
			if(cntB[k] != 0) return false;
			cntA[k - 1] += 2 * cntA[k];
		}

		return cntA[0] >= cntB[0];
	}

	String nextToken() throws IOException{
		while(!st.hasMoreTokens())
			st = new StringTokenizer(in.readLine());
		return st.nextToken();
	}
	long nextLong() throws IOException{
		return Long.parseLong(nextToken());
	}
	int nextInt() throws IOException{
		return Integer.parseInt(nextToken());
	}
	double nextDouble() throws IOException{
		return Double.parseDouble(nextToken());
	}
}

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
import java.util.InputMismatchException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.NoSuchElementException;
import java.io.Writer;
import java.math.BigInteger;
import java.io.InputStream;

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

class TaskA {
    public void solve(int testNumber, InputReader in, OutputWriter out) {
		int count = in.readInt();
		int length = in.readInt();
		int time = in.readInt() * 2;
		int[] delta = IOUtils.readIntArray(in, count);
		double full = time / length;
		int remaining = time % length;
		double answer = full / 4 * (long)count * (count - 1);
		int j = 0;
		int lap = 0;
		int plus = 0;
		for (int i = 0; i < count; i++) {
			while (delta[j] + lap - delta[i] <= remaining) {
				j++;
				if (j == count) {
					j = 0;
					lap = length;
					plus = count;
				}
			}
			answer += (j - i + plus - 1) / 4d;
		}
		out.printLine(answer);
    }
}

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

class OutputWriter {
	private final PrintWriter writer;

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

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

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

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

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

	}

class IOUtils {

	public static int[] readIntArray(InputReader in, int size) {
		int[] array = new int[size];
		for (int i = 0; i < size; i++)
			array[i] = in.readInt();
		return array;
	}

	}

import java.io.*;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.util.Map.Entry;

public class Main implements Runnable {
    static final int MOD = (int) 1e9 + 7;
    static final int MI = (int) 1e9;
    static final long ML = (long) 1e18;
    static final Reader in = new Reader();
    static final PrintWriter out = new PrintWriter(System.out);
    StringBuilder answer = new StringBuilder();
    Random random = new Random(751454315315L + System.currentTimeMillis());

    public static void main(String[] args) {
        new Thread(null, new Main(), "persefone", 1 << 28).start();
    }

    @Override
    public void run() {
        solve();
        printf();
        flush();
    }

    void solve() {
        int n = in.nextInt();
        int m = in.nextInt();
        int[] a = new int[31];
        for (int i = 0; i < n; i++) {
            int x = in.nextInt();
            for (int j = 0; j <= 30; j++) {
                if ((x & (1 << j)) > 0) {
                    a[j]++;
                }
            }
        }
        int[] b = new int[31];
        for (int i = 0; i < m; i++) {
            b[in.nextInt()]++;
        }
        int low = 0, high = m + 1, ans = 0;
        while (low < high) {
            int mid = low + high >> 1;
            int cur = mid;
            int[] c = new int[31];
            for (int i = 0; i <= 30; i++) {
                if (b[i] <= cur) {
                    c[i] = b[i];
                    cur -= b[i];
                } else {
                    cur = 0;
                    c[i] = cur;
                    break;
                }
            }

            for (int i = 0; i < 30; i++) {
                int d = a[i] > c[i] ? c[i] : a[i];
                c[i] -= d;
                c[i + 1] += c[i] + 1 >> 1;
            }

            if (c[30] == 0) {
                ans = mid;
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        printf(ans);
    }

    void printf() {
        out.print(answer);
    }

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

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

    void printf(Stream<?> str) {
        str.forEach(o -> add(o, " "));
        add("\n");
    }

    void printf(Object... obj) {
        printf(false, obj);
    }

    void printfWithDescription(Object... obj) {
        printf(true, obj);
    }

    private void printf(boolean b, Object... obj) {

        if (obj.length > 1) {
            for (int i = 0; i < obj.length; i++) {
                if (b) add(obj[i].getClass().getSimpleName(), " - ");
                if (obj[i] instanceof Collection<?>) {
                    printf((Collection<?>) obj[i]);
                } else if (obj[i] instanceof int[][]) {
                    printf((int[][]) obj[i]);
                } else if (obj[i] instanceof long[][]) {
                    printf((long[][]) obj[i]);
                } else if (obj[i] instanceof double[][]) {
                    printf((double[][]) obj[i]);
                } else printf(obj[i]);
            }
            return;
        }

        if (b) add(obj[0].getClass().getSimpleName(), " - ");
        printf(obj[0]);
    }

    void printf(Object o) {
        if (o instanceof int[])
            printf(Arrays.stream((int[]) o).boxed());
        else if (o instanceof char[])
            printf(new String((char[]) o));
        else if (o instanceof long[])
            printf(Arrays.stream((long[]) o).boxed());
        else if (o instanceof double[])
            printf(Arrays.stream((double[]) o).boxed());
        else if (o instanceof boolean[]) {
            for (boolean b : (boolean[]) o) add(b, " ");
            add("\n");
        } else
            add(o, "\n");
    }

    void printf(int[]... obj) {
        for (int i = 0; i < obj.length; i++) printf(obj[i]);
    }

    void printf(long[]... obj) {
        for (int i = 0; i < obj.length; i++) printf(obj[i]);
    }

    void printf(double[]... obj) {
        for (int i = 0; i < obj.length; i++) printf(obj[i]);
    }

    void printf(boolean[]... obj) {
        for (int i = 0; i < obj.length; i++) printf(obj[i]);
    }

    void printf(Collection<?> col) {
        printf(col.stream());
    }

    <T, K> void add(T t, K k) {
        if (t instanceof Collection<?>) {
            ((Collection<?>) t).forEach(i -> add(i, " "));
        } else if (t instanceof Object[]) {
            Arrays.stream((Object[]) t).forEach(i -> add(i, " "));
        } else
            add(t);
        add(k);
    }

    <T> void add(T t) {
        answer.append(t);
    }

    static class Reader {
        private BufferedReader br;
        private StringTokenizer st;

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

        Reader(String fileName) throws FileNotFoundException {
            br = new BufferedReader(new FileReader(fileName));
        }

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

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

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

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

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

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

import javax.swing.text.Segment;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class AtCoder implements Runnable {
    static final double time = 1e9;
    static final int MOD = (int) 1e9 + 7;
    static final long mh = Long.MAX_VALUE;
    static final Reader in = new Reader();
    static final PrintWriter out = new PrintWriter(System.out);
    StringBuilder answer = new StringBuilder();
    long start = System.nanoTime();

    public static void main(String[] args) {
        new Thread(null, new AtCoder(), "persefone", 1 << 28).start();
    }

    @Override
    public void run() {
        solve();
        printf();
        out.flush();
    }

    void solve() {
        int n = in.nextInt();
        int m = in.nextInt();
        int[] a = in.nextIntArray(n);
        Arrays.sort(a);
        int[] b = new int[m];
        for (int i = 0; i < m; i++) b[i] = 1 << in.nextInt();
        Arrays.sort(b);
        int ans = 0;
        int start = 0;
        for (int i = 0; i < n; i++) {
            for ( ; start < m; start++){
                if (a[i] < b[start]) break;
                ans++;
                a[i] -= b[start];
            }
            if (start == m) break;
        }
        printf(ans);

    }

    static class SearchUtils {
        static int lowerBound(int[] a, int l, int r, int k) {
            int m = 0, ans = r;
            while (l < r) if (a[m = l + r >> 1] >= k) ans = r = m; else l = m + 1;
            return ans;
        }

        static int upperBound(int[] a, int l, int r, int k) {
            int m = 0, ans = r;
            while (l < r) if (a[m = l + r >> 1] > k) ans = r = m; else l = m + 1;
            return ans;
        }
    }

    static class Fenwick {
        private int n = 100010;
        private int[] max;

        public Fenwick() {
            this.max = new int[n];
        }

        public void update(int i, int val) {
            for (; i < n; i += i & -i) max[i] = Math.max(max[i], val);
        }

        public int get(int i) {
            int ans = 0;
            for (; i > 0; i -= i & -i) ans = Math.max(ans, max[i]);
            return ans;
        }

        public void refresh() {
            Arrays.fill(max, 0);
        }
    }

    interface SegmentTree<T> {
        void build(int currentVertex, int currentLeft, int currentRight);
        void update(int currentVertex, int currentLeft, int currentRight, int pos, int value);
        T calc(T a, T b);
        T get(int currentVertex, int currentLeft, int currentRight, int left, int right);
    }

    static class SegmentTreeMax implements SegmentTree<Integer> {
        private int n;
        private int[] a;
        private int[] max;

        public SegmentTreeMax(int[] a, int n) {
            this.a = a;
            this.n = n;
            this.max = new int[4 * n + 4];
            build(1, 0, n - 1);
        }

        @Override
        public void build (int currentVertex, int currentLeft, int currentRight) {
            if (currentLeft == currentRight) max[currentVertex] = a[currentLeft];
            else {
                int middle = currentLeft + currentRight >> 1, doubleVex = currentVertex << 1;
                build(doubleVex, currentLeft, middle);
                build(doubleVex + 1, middle + 1, currentRight);
                max[currentVertex] = calc(max[doubleVex], max[doubleVex + 1]);
            }
        }

        @Override
        public Integer calc(Integer x, Integer y) {
            return Math.max(x, y);
        }

        @Override
        public void update(int currentVertex, int currentLeft, int currentRight, int pos, int value) {
            if (currentLeft == currentRight) max[currentVertex] = value;
            else {
                int middle = currentLeft + currentRight >> 1, doubleVex = currentVertex << 1;
                if (pos <= middle && pos >= currentLeft)
                    update(doubleVex, currentLeft, middle, pos, value);
                else
                    update(doubleVex + 1, middle + 1, currentRight, pos, value);
                max[currentVertex] = calc(max[doubleVex], max[doubleVex + 1]);
            }
        }

        void update(int pos, int value) {
            update(1, 0, n - 1, pos, value);
        }

        @Override
        public Integer get(int currentVertex, int currentLeft, int currentRight, int left, int right) {
            if (currentLeft > right || currentRight < left) return -1;
            else if (currentLeft >= left && currentRight <= right) return max[currentVertex];
            else {
                int middle = currentLeft + currentRight >> 1, doubleVex = currentVertex << 1;
                return calc(get(doubleVex, currentLeft, middle, left, right), get(doubleVex + 1, middle + 1, currentRight, left, right));

            }
        }

        Integer get(int left, int right) {
            return get(1, 0, n - 1, left, right);
        }

    }

    interface SparseTable {
        int function(int a, int b);
        void build();
        int get(int l, int r);
    }

    static class SparseTable_Gcd implements SparseTable {
        private int n, MAX_LENGTH;
        private int[] log;
        private int[][] gcd;

        public SparseTable_Gcd(int[] a, int n) {
            this.n = n;
            this.log = new int[n + 1];
            for (int i = 2; i <= n; i++) log[i] = log[i >> 1] + 1;
            this.MAX_LENGTH = log[n];
            this.gcd = new int[n + 1][MAX_LENGTH + 1];
            for (int i = 0; i < n; i++) gcd[i][0] = a[i];
            build();
        }

        @Override
        public int function(int a, int b) {
            return b == 0 ? a : function(b, a % b);
        }

        @Override
        public void build() {
            for (int j = 1; j <= MAX_LENGTH; j++)
                for (int i = 0; i <= n - (1 << j); i++)
                    gcd[i][j] = function(gcd[i][j - 1], gcd[i + (1 << j - 1)][j - 1]);
        }

        @Override
        public int get(int l, int r) {
            int k = log[r - l + 1];
            return function(gcd[l][k], gcd[r - (1 << k) + 1][k]);
        }

        int findLeft(int l, int r, int k) {
            int m = 0, R = r, ans = 0, g = 0, t = 0;
            while (l < r) {
                m = l + r >> 1;
                if ((t = get(m, R)) >= k) { ans = r = m; g = t; } else l = m + 1;
            }
            return g == k ? ans : R;
        }

        int findRight(int l, int r, int k) {
            int m = 0, L = l, ans = 0, g = 0, t = 0;
            while (l < r) {
                m = l + r >> 1;
                if ((t = get(L, m)) >= k) { ans = m; l = m + 1; g = t; } else r = m;
            }
            return g == k ? ans : L;
        }

        int find(int cur, int k) {
            return findRight(cur, n, k) - findLeft(0, cur, k) + 1;
        }

    }

    static class SegmentTreeMin {
        private int n;
        private int[] min, a;

        public SegmentTreeMin(int[] a, int n) {
            this.n = n;
            this.a = a;
            this.min = new int[4 * n + 4];
            build(1, 0, n - 1);
        }

        private void build(int currentVertex, int currentLeft, int currentRight) {
            if (currentLeft == currentRight) min[currentVertex] = a[currentLeft];
            else {
                int middle = currentLeft + currentRight >> 1, doubleVex = currentVertex << 1;
                build(doubleVex, currentLeft, middle);
                build(doubleVex + 1, middle + 1, currentRight);
                min[currentVertex] = Math.min(min[doubleVex], min[doubleVex + 1]);
            }
        }

        private void update(int currentVertex, int currentLeft, int currentRight, int pos, int value) {
            if (currentLeft == currentRight) min[currentVertex] = a[pos] = value;
            else {
                int middle = currentLeft + currentRight >> 1, doubleVex = currentVertex << 1;
                if (pos <= middle && pos >= currentLeft)
                    update(doubleVex, currentLeft, middle, pos, value);
                else
                    update(doubleVex + 1, middle + 1, currentRight, pos, value);
                min[currentVertex] = Math.min(min[doubleVex], min[doubleVex + 1]);
            }
        }

        public void update(int pos, int value) {
            update(1, 0, n - 1, pos, value);
        }

        private int getMin(int currentVertex, int currentLeft, int currentRight, int left, int right) {
            if (left > currentRight || right < currentLeft) return Integer.MAX_VALUE;
            if (currentLeft >= left && currentRight <= right) return min[currentVertex];
            int middle = currentLeft + currentRight >> 1, doubleVex = currentVertex << 1;
            return Math.min(getMin(doubleVex, currentLeft, middle, left, right),
                    getMin(doubleVex + 1, middle + 1, currentRight, left, right));
        }

        public int getMin(int left, int right) {
            return getMin(1, 0, n - 1, left, right);
        }
    }

    static class ArrayUtils {
        static void compressed(int[] a, int n) {
            int[] b = a.clone();
            Arrays.sort(b, 0, n);
            for (int i = 0; i < n; i++) a[i] = lw(b, 0, n, a[i]) + 1;
        }

        static int lw(int[] b, int l, int r, int k) {
            int R = r, m = 0;
            while (l <= r) {
                m = l + r >> 1;
                if (m == R) return m;
                if (b[m] >= k) r = m - 1;
                else l = m + 1;
            }
            return l;
        }

        static void compressed(long[] a, int n) {
            long[] b = a.clone();
            Arrays.sort(b, 0, n);
            for (int i = 0; i < n; i++) a[i] = lw(b, 0, n, a[i]) + 1;
        }

        static int lw(long[] b, int l, int r, long k) {
            int R = r, m = 0;
            while (l <= r) {
                m = l + r >> 1;
                if (m == R) return m;
                if (b[m] >= k) r = m - 1;
                else l = m + 1;
            }
            return l;
        }

        static int up(int[] b, int l, int r, int k) {
            int R = r, m = 0;
            while (l <= r) {
                m = l + r >> 1;
                if (m == R) return m;
                if (b[m] > k) r = m - 1;
                else l = m + 1;
            }
            return l;
        }
    }

    static class ListUtils {
        static <T extends Comparable<T>> int upperBound(List<T> list, int l, int r, T t) {
            int R = r, m = 0;
            while (l <= r) {
                m = l + r >> 1;
                if (R == m) return m;
                if (list.get(m).compareTo(t) > 0)
                    r = m - 1;
                else
                    l = m + 1;
            }
            return l;
        }

        static <T extends Comparable<T>> int lowerBound(List<T> list, int l, int r, T t) {
            int R = r, m = 0;
            while (l <= r) {
                m = l + r >> 1;
                if (R == m) return m;
                if (list.get(m).compareTo(t) >= 0)
                    r = m - 1;
                else
                    l = m + 1;
            }
            return l;
        }

    }

    void printf() {
        out.print(answer);
    }

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

    void printf(Stream<?> str) {
        str.forEach(o -> add(o, " "));
        add("\n");
    }

    void printf(Object... obj) {
        printf(false, obj);
    }

    void printfWithDescription(Object... obj) {
        printf(true, obj);
    }

    private void printf(boolean b, Object... obj) {

        if (obj.length > 1) {
            for (int i = 0; i < obj.length; i++) {
                if (b) add(obj[i].getClass().getSimpleName(), " - ");
                if (obj[i] instanceof Collection<?>) {
                    printf((Collection<?>) obj[i]);
                } else if (obj[i] instanceof int[][]) {
                    printf((int[][]) obj[i]);
                } else if (obj[i] instanceof long[][]) {
                    printf((long[][]) obj[i]);
                } else if (obj[i] instanceof double[][]) {
                    printf((double[][]) obj[i]);
                } else printf(obj[i]);
            }
            return;
        }

        if (b) add(obj[0].getClass().getSimpleName(), " - ");
        printf(obj[0]);
    }

    void printf(Object o) {
        if (o instanceof int[])
            printf(Arrays.stream((int[]) o).boxed());
        else if (o instanceof char[])
            printf(new String((char[]) o));
        else if (o instanceof long[])
            printf(Arrays.stream((long[]) o).boxed());
        else if (o instanceof double[])
            printf(Arrays.stream((double[]) o).boxed());
        else if (o instanceof boolean[]) {
            for (boolean b : (boolean[]) o) add(b, " ");
            add("\n");
        } else
            add(o, "\n");
    }

    void printf(int[]... obj) {
        for (int i = 0; i < obj.length; i++) printf(obj[i]);
    }

    void printf(long[]... obj) {
        for (int i = 0; i < obj.length; i++) printf(obj[i]);
    }

    void printf(double[]... obj) {
        for (int i = 0; i < obj.length; i++) printf(obj[i]);
    }

    void printf(boolean[]... obj) {
        for (int i = 0; i < obj.length; i++) printf(obj[i]);
    }

    void printf(Collection<?> col) {
        printf(col.stream());
    }

    <T, K> void add(T t, K k) {
        if (t instanceof Collection<?>) {
            ((Collection<?>) t).forEach(i -> add(i, " "));
        } else if (t instanceof Object[]) {
            Arrays.stream((Object[]) t).forEach(i -> add(i, " "));
        } else
            add(t);
        add(k);
    }

    <T> void add(T t) {
        answer.append(t);
    }

    @SuppressWarnings("unchecked")
    <T extends Comparable<? super T>> T min(T... t) {
        if (t.length == 0)
            return null;
        T m = t[0];
        for (int i = 1; i < t.length; i++)
            if (t[i].compareTo(m) < 0)
                m = t[i];
        return m;
    }

    @SuppressWarnings("unchecked")
    <T extends Comparable<? super T>> T max(T... t) {
        if (t.length == 0)
            return null;
        T m = t[0];
        for (int i = 1; i < t.length; i++)
            if (t[i].compareTo(m) > 0)
                m = t[i];
        return m;
    }

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

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

    // c = gcd(a, b) -> extends gcd method: ax + by = c <----> (b % a)p + q = c;
    int[] ext_gcd(int a, int b) {
        if (b == 0) return new int[]{a, 1, 0};
        int[] vals = ext_gcd(b, a % b);
        int d = vals[0]; // gcd
        int p = vals[2]; //
        int q = vals[1] - (a / b) * vals[2];
        return new int[]{d, p, q};
    }

    // find any solution of the equation: ax + by = c using extends gcd
    boolean find_any_solution(int a, int b, int c, int[] root) {
        int[] vals = ext_gcd(Math.abs(a), Math.abs(b));
        if (c % vals[0] != 0) return false;
        printf(vals);
        root[0] = c * vals[1] / vals[0];
        root[1] = c * vals[2] / vals[0];
        if (a < 0) root[0] *= -1;
        if (b < 0) root[1] *= -1;
        return true;
    }

    int mod(int x) {
        return x % MOD;
    }

    int mod(int x, int y) {
        return mod(mod(x) + mod(y));
    }

    long mod(long x) {
        return x % MOD;
    }

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

    int lw(long[] f, int l, int r, long k) {
        int R = r, m = 0;
        while (l <= r) {
            m = l + r >> 1;
            if (m == R) return m;
            if (f[m] >= k) r = m - 1;
            else l = m + 1;
        }
        return l;
    }

    int up(long[] f, int l, int r, long k) {
        int R = r, m = 0;
        while (l <= r) {
            m = l + r >> 1;
            if (m == R) return m;
            if (f[m] > k) r = m - 1;
            else l = m + 1;
        }
        return l;
    }

    int lw(int[] f, int l, int r, int k) {
        int R = r, m = 0;
        while (l <= r) {
            m = l + r >> 1;
            if (m == R) return m;
            if (f[m] >= k) r = m - 1;
            else l = m + 1;
        }
        return l;
    }

    int up(int[] f, int l, int r, int k) {
        int R = r, m = 0;
        while (l <= r) {
            m = l + r >> 1;
            if (m == R) return m;
            if (f[m] > k) r = m - 1;
            else l = m + 1;
        }
        return l;
    }

    <K extends Comparable<K>> int lw(List<K> li, int l, int r, K k) {
        int R = r, m = 0;
        while (l <= r) {
            m = l + r >> 1;
            if (m == R) return m;
            if (li.get(m).compareTo(k) >= 0)
                r = m - 1;
            else
                l = m + 1;
        }
        return l;
    }

    <K extends Comparable<K>> int up(List<K> li, int l, int r, K k) {
        int R = r, m = 0;
        while (l <= r) {
            m = l + r >> 1;
            if (m == R) return m;
            if (li.get(m).compareTo(k) > 0)
                r = m - 1;
            else
                l = m + 1;
        }
        return l;
    }

    <K extends Comparable<K>> int bs(List<K> li, int l, int r, K k) {
        while (l <= r) {
            int m = l + r >> 1;
            if (li.get(m) == k) return m;
            else if (li.get(m).compareTo(k) < 0)
                l = m + 1;
            else
                r = m - 1;
        }
        return -1;
    }

    long calc(int base, int exponent) {
        if (exponent == 0) return 1;
        if (exponent == 1) return base % MOD;
        long m = calc(base, exponent / 2);
        if (exponent % 2 == 0) return (m * m) % MOD;
        return (base * ((m * m) % MOD)) % MOD;
    }

    long calc(int base, long exponent) {
        if (exponent == 0) return 1;
        if (exponent == 1) return base % MOD;
        long m = calc(base, exponent / 2);
        if (exponent % 2 == 0) return (m * m) % MOD;
        return (base * ((m * m) % MOD)) % MOD;
    }

    long calc(long base, long exponent) {
        if (exponent == 0) return 1;
        if (exponent == 1) return base % MOD;
        long m = calc(base, exponent / 2);
        if (exponent % 2 == 0) return (m * m) % MOD;
        return (base * (m * m % MOD)) % MOD;
    }

    long power(int base, int exponent) {
        if (exponent == 0) return 1;
        long m = power(base, exponent / 2);
        if (exponent % 2 == 0) return m * m;
        return base * m * m;
    }

    void swap(int[] a, int i, int j) {
        a[i] ^= a[j];
        a[j] ^= a[i];
        a[i] ^= a[j];
    }

    void swap(long[] a, int i, int j) {
        long tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }

    static class Pair<K extends Comparable<? super K>, V extends Comparable<? super V>>
            implements Comparable<Pair<K, V>> {
        private K k;
        private V v;

        Pair() {
        }

        Pair(K k, V v) {
            this.k = k;
            this.v = v;
        }

        K getK() {
            return k;
        }

        V getV() {
            return v;
        }

        void setK(K k) {
            this.k = k;
        }

        void setV(V v) {
            this.v = v;
        }

        void setKV(K k, V v) {
            this.k = k;
            this.v = v;
        }

        @SuppressWarnings("unchecked")
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || !(o instanceof Pair)) return false;
            Pair<K, V> p = (Pair<K, V>) o;
            return k.compareTo(p.k) == 0 && v.compareTo(p.v) == 0;
        }

        @Override
        public int hashCode() {
            int hash = 31;
            hash = hash * 89 + k.hashCode();
            hash = hash * 89 + v.hashCode();
            return hash;
        }

        @Override
        public int compareTo(Pair<K, V> pair) {
            return k.compareTo(pair.k) == 0 ? v.compareTo(pair.v) : k.compareTo(pair.k);
        }

        @Override
        public Pair<K, V> clone() {
            return new Pair<K, V>(this.k, this.v);
        }

        @Override
        public String toString() {
            return String.valueOf(k).concat(" ").concat(String.valueOf(v)).concat("\n");
        }
    }

    static class Reader {
        private BufferedReader br;
        private StringTokenizer st;

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

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

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

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

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

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

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

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

public class C309 {

	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner(System.in);
		PrintWriter pw = new PrintWriter(System.out);
		int n = sc.nextInt();
		int m = sc.nextInt();
		int[] cntav = new int[32];
		while (n-- > 0) {
			int x = sc.nextInt();
			int mult = 0;
			while (x > 0) {
				if (x % 2 == 1)
					cntav[mult]++;
				mult++;
				x >>= 1;
			}
		}
		int[] cntnd = new int[32];
		while (m-- > 0) {
			int x = sc.nextInt();
			cntnd[x]++;
		}
		int ans = 0;
//		pw.println(Arrays.toString(cntav));
//		pw.println(Arrays.toString(cntnd));
		for (int i = 0; i < 32; i++) {
			int mult = 1;
			int j = i;
			while (cntnd[i] > 0 && j<32) {
//				pw.println(Arrays.toString(cntav));
//				pw.println(Arrays.toString(cntnd));
				int min = Math.min(cntnd[i], cntav[j] * mult);
				cntnd[i] -= min;
				cntav[j] -= min % mult == 0 ? min / mult : min / mult + 1;
				mult *= 2;
				ans += min;
				j++;
			}

		}
		pw.println(ans);
		pw.close();
	}

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

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

		public Scanner(FileReader r) {
			br = new BufferedReader(r);
		}

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

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

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

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

		public double nextDouble() throws IOException {
			String x = next();
			StringBuilder sb = new StringBuilder("0");
			double res = 0, f = 1;
			boolean dec = false, neg = false;
			int start = 0;
			if (x.charAt(0) == '-') {
				neg = true;
				start++;
			}
			for (int i = start; i < x.length(); i++)
				if (x.charAt(i) == '.') {
					res = Long.parseLong(sb.toString());
					sb = new StringBuilder("0");
					dec = true;
				} else {
					sb.append(x.charAt(i));
					if (dec)
						f *= 10;
				}
			res += Long.parseLong(sb.toString()) / f;
			return res * (neg ? -1 : 1);
		}

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

	}
}

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

public class C309 {

	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner(System.in);
		PrintWriter pw = new PrintWriter(System.out);
		int n = sc.nextInt();
		int m = sc.nextInt();
		int[] cntav = new int[32];
		while (n-- > 0) {
			int x = sc.nextInt();
			int mult = 0;
			while (x > 0) {
				if (x % 2 == 1)
					cntav[mult]++;
				mult++;
				x >>= 1;
			}
		}
		int[] cntnd = new int[32];
		while (m-- > 0) {
			int x = sc.nextInt();
			cntnd[x]++;
		}
		int ans = 0;
//		pw.println(Arrays.toString(cntav));
//		pw.println(Arrays.toString(cntnd));
		for (int i = 0; i < 32; i++) {
			int j = i;
			int need = cntnd[i] << i;
			while (need > 0 && j<32) {
//				pw.println(Arrays.toString(cntav));
//				pw.println(Arrays.toString(cntnd));
				int av = cntav[j] << j;

				int min = Math.min(av, need);
				need -= min;
				av -= min;
				ans+=min/(1<<i);
				cntav[j] = av / (1 << j);
				av -= cntav[j]*(1<<j);
				int idx = 0;
//				pw.println(av);
				while (av > 0) {
//					pw.println(av);
					if (av % 2 == 1)
						cntav[idx]++;
					idx++;
					av >>= 1;
				}
				j++;
			}

		}
		pw.println(ans);
		pw.close();
	}

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

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

		public Scanner(FileReader r) {
			br = new BufferedReader(r);
		}

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

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

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

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

		public double nextDouble() throws IOException {
			String x = next();
			StringBuilder sb = new StringBuilder("0");
			double res = 0, f = 1;
			boolean dec = false, neg = false;
			int start = 0;
			if (x.charAt(0) == '-') {
				neg = true;
				start++;
			}
			for (int i = start; i < x.length(); i++)
				if (x.charAt(i) == '.') {
					res = Long.parseLong(sb.toString());
					sb = new StringBuilder("0");
					dec = true;
				} else {
					sb.append(x.charAt(i));
					if (dec)
						f *= 10;
				}
			res += Long.parseLong(sb.toString()) / f;
			return res * (neg ? -1 : 1);
		}

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

	}
}

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

public class C309 {

	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner(System.in);
		PrintWriter pw = new PrintWriter(System.out);
		int n = sc.nextInt();
		int m = sc.nextInt();
		int[] cntav = new int[32];
		while (n-- > 0) {
			int x = sc.nextInt();
			int mult = 0;
			while (x > 0) {
				if (x % 2 == 1)
					cntav[mult]++;
				mult++;
				x >>= 1;
			}
		}
		int[] cntnd = new int[32];
		while (m-- > 0) {
			int x = sc.nextInt();
			cntnd[x]++;
		}
		int ans = 0;
//		pw.println(Arrays.toString(cntav));
//		pw.println(Arrays.toString(cntnd));
		for (int i = 0; i < 32; i++) {
			int mult = 1;
			int j = i;
			while (cntnd[i] > 0 && j < 32) {
//				pw.println(Arrays.toString(cntav));
//				pw.println(Arrays.toString(cntnd));
				int min = Math.min(cntnd[i], cntav[j] * mult);
				cntnd[i] -= min;
				int x = (1 << j) - (min % (1 << j));
				int idx = 0;
				while (x > 0) {
					if (x % 2 == 1) {
						cntav[idx++]++;
					}
					x >>= 1;
				}
				cntav[j] -= min % mult == 0 ? min / mult : min / mult + 1;
				mult *= 2;
				ans += min;
				j++;
			}

		}
		pw.println(ans);
		pw.close();
	}

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

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

		public Scanner(FileReader r) {
			br = new BufferedReader(r);
		}

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

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

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

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

		public double nextDouble() throws IOException {
			String x = next();
			StringBuilder sb = new StringBuilder("0");
			double res = 0, f = 1;
			boolean dec = false, neg = false;
			int start = 0;
			if (x.charAt(0) == '-') {
				neg = true;
				start++;
			}
			for (int i = start; i < x.length(); i++)
				if (x.charAt(i) == '.') {
					res = Long.parseLong(sb.toString());
					sb = new StringBuilder("0");
					dec = true;
				} else {
					sb.append(x.charAt(i));
					if (dec)
						f *= 10;
				}
			res += Long.parseLong(sb.toString()) / f;
			return res * (neg ? -1 : 1);
		}

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

	}
}

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

public class C309 {

	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner(System.in);
		PrintWriter pw = new PrintWriter(System.out);
		int n = sc.nextInt();
		int m = sc.nextInt();
		int[] cntav = new int[32];
		while (n-- > 0) {
			int x = sc.nextInt();
			int mult = 0;
			while (x > 0) {
				if (x % 2 == 1)
					cntav[mult]++;
				mult++;
				x >>= 1;
			}
		}
		int[] cntnd = new int[32];
		while (m-- > 0) {
			int x = sc.nextInt();
			cntnd[x]++;
		}
		int ans = 0;
//		pw.println(Arrays.toString(cntav));
//		pw.println(Arrays.toString(cntnd));
		for (int i = 0; i < 32; i++) {
			int mult = 1;
			int j = i;
			while (cntnd[i] > 0 && j < 32) {
//				pw.println(Arrays.toString(cntav));
//				pw.println(Arrays.toString(cntnd));
				int min = Math.min(cntnd[i], cntav[j] * mult);
				cntnd[i] -= min;
				int x = (1 << j) - (min % (1 << j));
				int idx = 0;
				while (x > 0) {
					if (x % 2 == 1) {
						cntav[idx]++;
					}
					idx++;
					x >>= 1;
				}
				cntav[j] -= min % mult == 0 ? min / mult : min / mult + 1;
				mult *= 2;
				ans += min;
				j++;
			}

		}
		pw.println(ans);
		pw.close();
	}

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

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

		public Scanner(FileReader r) {
			br = new BufferedReader(r);
		}

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

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

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

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

		public double nextDouble() throws IOException {
			String x = next();
			StringBuilder sb = new StringBuilder("0");
			double res = 0, f = 1;
			boolean dec = false, neg = false;
			int start = 0;
			if (x.charAt(0) == '-') {
				neg = true;
				start++;
			}
			for (int i = start; i < x.length(); i++)
				if (x.charAt(i) == '.') {
					res = Long.parseLong(sb.toString());
					sb = new StringBuilder("0");
					dec = true;
				} else {
					sb.append(x.charAt(i));
					if (dec)
						f *= 10;
				}
			res += Long.parseLong(sb.toString()) / f;
			return res * (neg ? -1 : 1);
		}

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

	}
}

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

public class Main {

	static class FastScanner {
		BufferedReader s;
		StringTokenizer st;

		public FastScanner(InputStream InputStream) {
			st = new StringTokenizer("");
			s = new BufferedReader(new InputStreamReader(InputStream));
		}

		public FastScanner(File f) throws FileNotFoundException {
			st = new StringTokenizer("");
			s = new BufferedReader(new FileReader(f));
		}

		public int nextInt() throws IOException {
			if (st.hasMoreTokens())
				return Integer.parseInt(st.nextToken());
			else {
				st = new StringTokenizer(s.readLine());
				return nextInt();
			}
		}

		public BigInteger big() throws IOException {
			if (st.hasMoreTokens())
				return new BigInteger(st.nextToken());
			else {
				st = new StringTokenizer(s.readLine());
				return big();
			}
		}

		public double nextDouble() throws IOException {
			if (st.hasMoreTokens())
				return Double.parseDouble(st.nextToken());
			else {
				st = new StringTokenizer(s.readLine());
				return nextDouble();
			}
		}

		public long nextLong() throws IOException {
			if (st.hasMoreTokens())
				return Long.parseLong(st.nextToken());
			else {
				st = new StringTokenizer(s.readLine());
				return nextLong();
			}
		}

		public String next() throws IOException {
			if (st.hasMoreTokens())
				return st.nextToken();
			else {
				st = new StringTokenizer(s.readLine());
				return next();
			}

		}

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

		public void close() throws IOException {
			s.close();
		}

	}

	public static void main(String[] args) throws IOException {
		FastScanner in = new FastScanner(System.in);
		int n = in.nextInt(), m = in.nextInt();
		int[] bits= new int[32];
		for(int x = 0; x < n; x++) {
			int  val = in.nextInt();
			for(int i = 0; i < 32; i++) {
				int mask = (1<<i);
				if((val & mask) != 0)
					bits[i]++;
			}
 		}
		ArrayList<Integer> arr = new ArrayList<Integer>();
		for(int x = 0; x < m; x++)
			arr.add(in.nextInt());
		Collections.sort(arr);
		int ans = 0, high = 31;
		for(int x = 0; x < m; x++) {
			int val = arr.get(x);
			if(bits[val] > 0) {
				bits[val]--;
				ans++;
			}
			else {
				high = val + 1;
				while(high < 32 && bits[high] == 0) high--;
				if(high < 32) {
					bits[high]--;
					ans++;
					for(int i = val; i < high; i++)
						bits[i]++;
				}
			}
		}
		System.out.println(ans);
	}

}

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

public class Main {

	static class FastScanner {
		BufferedReader s;
		StringTokenizer st;

		public FastScanner(InputStream InputStream) {
			st = new StringTokenizer("");
			s = new BufferedReader(new InputStreamReader(InputStream));
		}

		public FastScanner(File f) throws FileNotFoundException {
			st = new StringTokenizer("");
			s = new BufferedReader(new FileReader(f));
		}

		public int nextInt() throws IOException {
			if (st.hasMoreTokens())
				return Integer.parseInt(st.nextToken());
			else {
				st = new StringTokenizer(s.readLine());
				return nextInt();
			}
		}

		public BigInteger big() throws IOException {
			if (st.hasMoreTokens())
				return new BigInteger(st.nextToken());
			else {
				st = new StringTokenizer(s.readLine());
				return big();
			}
		}

		public double nextDouble() throws IOException {
			if (st.hasMoreTokens())
				return Double.parseDouble(st.nextToken());
			else {
				st = new StringTokenizer(s.readLine());
				return nextDouble();
			}
		}

		public long nextLong() throws IOException {
			if (st.hasMoreTokens())
				return Long.parseLong(st.nextToken());
			else {
				st = new StringTokenizer(s.readLine());
				return nextLong();
			}
		}

		public String next() throws IOException {
			if (st.hasMoreTokens())
				return st.nextToken();
			else {
				st = new StringTokenizer(s.readLine());
				return next();
			}

		}

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

		public void close() throws IOException {
			s.close();
		}

	}

	public static void main(String[] args) throws IOException {
		FastScanner in = new FastScanner(System.in);
		int n = in.nextInt(), m = in.nextInt();
		int[] bits= new int[32];
		for(int x = 0; x < n; x++) {
			int  val = in.nextInt();
			for(int i = 0; i < 32; i++) {
				int mask = (1<<i);
				if((val & mask) != 0)
					bits[i]++;
			}
 		}
		ArrayList<Integer> arr = new ArrayList<Integer>();
		for(int x = 0; x < m; x++)
			arr.add(in.nextInt());
		Collections.sort(arr);
		int ans = 0, high = 31;
		for(int x = 0; x < m; x++) {
			int val = arr.get(x);
			if(bits[val] > 0) {
				bits[val]--;
				ans++;
			}
			else {
				while(high > 0 && bits[high] == 0) high--;
				if(high > val) {
					bits[high]--;
					ans++;
					for(int i = val; i < high; i++)
						bits[i]++;
				}
			}
		}
		System.out.println(ans);
	}

}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

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

    static class CMemoryForArrays {
        private InputReader in;
        private PrintWriter out;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            this.in = in;
            this.out = out;
            int n = in.nextInt();
            int m = in.nextInt();
            int[] a = in.nextIntArray(n, 1);
            int[] b = in.nextIntArray(m, 1);
            QuickSort.sort(a, 1, n);
            QuickSort.sort(b, 1, m);
            int cur = 1;
            int ans = 0;
            for (int i = 1; i <= m; i++) {
                while (a[cur] < (1 << b[i])) {
                    cur++;
                    if (cur > n) {
                        out.println(ans);
                        return;
                    }
                }
                ans++;
                a[cur] -= (1 << b[i]);
            }
            out.println(ans);
        }

    }

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

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

        public int read() {
            if (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 int[] nextIntArray(int length, int stIndex) {
            int[] arr = new int[length + stIndex];
            for (int i = stIndex; i < stIndex + length; i++)
                arr[i] = nextInt();
            return arr;
        }

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

    }

    static class QuickSort {
        public static void sort(int[] list, int lowIndex, int highIndex) {
            ArrayAlgorithm.shuffleArray(list, lowIndex, highIndex);
            Arrays.sort(list, lowIndex, highIndex + 1);
        }

    }

    static class ArrayAlgorithm {
        public static void shuffleArray(int[] array, int stIndex, int enIndex) {
            for (int i = enIndex; i > stIndex; i--) {
                int index = (int) OneNumberGen.genInt(stIndex, i - 1);
                if (index != i) {
                    array[index] ^= array[i];
                    array[i] ^= array[index];
                    array[index] ^= array[i];
                }
            }
        }

    }

    static class OneNumberGen {
        private static long genI(long min, long max) {
            return ThreadLocalRandom.current().nextLong(min, max + 1);
        }

        public static long genInt(long min, long max) {
            if (min >= 0)
                return (genI(min, max));
            else if (max >= 0) {
                double ratio = (double) Math.abs(min) / (Math.abs(min) + max);
                ratio *= 1000000000000000000D;
                double prob = (double) (OneNumberGen.genInt(1, 1000000000000000000L));
                if (Double.compare(ratio, prob) > 0) {
                    return -(genI(0, -min));
                } else {
                    return (genI(0, max));
                }
            } else
                return -(OneNumberGen.genI(-min, -max));
        }

    }
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

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

    static class CMemoryForArrays {
        private InputReader in;
        private PrintWriter out;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            this.in = in;
            this.out = out;
            int n = in.nextInt();
            int m = in.nextInt();
            int[] a = in.nextIntArray(n, 1);
            int[] b = in.nextIntArray(m, 1);
            int[] cnt = new int[31];
            QuickSort.sort(b, 1, m);
            for (int i = 1; i <= n; i++) {
                for (int j = 0; j <= 30; j++) {
                    if (((a[i] >> j) & 1) == 1) {
                        cnt[j]++;
                    }
                }
            }
//        for (int i = 0; i <= 3; i++) {
//            out.print(cnt[i] + " ");
//        }
//        out.println();
            int cur = 30;
            int ans = 0;
            for (int i = m; i >= 1; i--) {
                while (cnt[cur] == 0) {
                    cur--;
                    if (cur == -1) {
                        out.println(ans);
                        return;
                    }
                }
                if (b[i] > cur) continue;
                ans++;
                cnt[cur]--;
                int tmp = cur;
                tmp--;
                while (tmp >= b[i]) {
                    cnt[tmp]++;
                    tmp--;
                }
            }
            out.println(ans);
        }

    }

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

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

        public int read() {
            if (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 int[] nextIntArray(int length, int stIndex) {
            int[] arr = new int[length + stIndex];
            for (int i = stIndex; i < stIndex + length; i++)
                arr[i] = nextInt();
            return arr;
        }

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

    }

    static class QuickSort {
        public static void sort(int[] list, int lowIndex, int highIndex) {
            ArrayAlgorithm.shuffleArray(list, lowIndex, highIndex);
            Arrays.sort(list, lowIndex, highIndex + 1);
        }

    }

    static class ArrayAlgorithm {
        public static void shuffleArray(int[] array, int stIndex, int enIndex) {
            for (int i = enIndex; i > stIndex; i--) {
                int index = (int) OneNumberGen.genInt(stIndex, i - 1);
                if (index != i) {
                    array[index] ^= array[i];
                    array[i] ^= array[index];
                    array[index] ^= array[i];
                }
            }
        }

    }

    static class OneNumberGen {
        private static long genI(long min, long max) {
            return ThreadLocalRandom.current().nextLong(min, max + 1);
        }

        public static long genInt(long min, long max) {
            if (min >= 0)
                return (genI(min, max));
            else if (max >= 0) {
                double ratio = (double) Math.abs(min) / (Math.abs(min) + max);
                ratio *= 1000000000000000000D;
                double prob = (double) (OneNumberGen.genInt(1, 1000000000000000000L));
                if (Double.compare(ratio, prob) > 0) {
                    return -(genI(0, -min));
                } else {
                    return (genI(0, max));
                }
            } else
                return -(OneNumberGen.genI(-min, -max));
        }

    }
}

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

public class TestGenerator {
    static final int mod = 998244353;

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        PrintWriter wr = new PrintWriter(System.out);

        int n = sc.nextInt();
        int m = sc.nextInt();
        int[] a = new int[33];
        int[] b = new int[33];
        for (int i = 0; i < n; i++) {
            int x = sc.nextInt();
            for (int j = 0; j < 32 && x > 0; j++, x >>= 1)
                if((x&1) == 1)
                    a[j]++;
        }
        for (int i = 0; i < m; i++) {
            b[sc.nextInt()]++;
        }
        int ans = 0;
        for (int i = 0; i < 32; i++) {
            long x = a[i] * (1 << i);
            for (int j = 0; j <= i; j++) {
                long min = Math.min(x >> j, b[j]);
                b[j] -= min;
                ans += min;
                x -= min << j;
            }
        }
        wr.println(ans);

        wr.close();
    }

    static int[] RandomizeArray(int[] array){
        Random rgen = new Random();  // Random number generator

        for (int i=0; i<array.length; i++) {
            int randomPosition = rgen.nextInt(array.length);
            int temp = array[i];
            array[i] = array[randomPosition];
            array[randomPosition] = temp;
        }

        return array;
    }
}

class Scanner
{
    StringTokenizer st;
    BufferedReader br;

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

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

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

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

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

    public double nextDouble() throws IOException
    {
        String x = next();
        StringBuilder sb = new StringBuilder("0");
        double res = 0, f = 1;
        boolean dec = false, neg = false;
        int start = 0;
        if(x.charAt(0) == '-')
        {
            neg = true;
            start++;
        }
        for(int i = start; i < x.length(); i++)
            if(x.charAt(i) == '.')
            {
                res = Long.parseLong(sb.toString());
                sb = new StringBuilder("0");
                dec = true;
            }
            else
            {
                sb.append(x.charAt(i));
                if(dec)
                    f *= 10;
            }
        res += Long.parseLong(sb.toString()) / f;
        return res * (neg?-1:1);
    }

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

}

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

public class TestGenerator {
    static final int mod = 998244353;

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        PrintWriter wr = new PrintWriter(System.out);

        int n = sc.nextInt();
        int m = sc.nextInt();
        int[] a = new int[n];
        int[] b = new int[m];
        for (int i = 0; i < n; i++) {
            a[i] = sc.nextInt();
        }
        for (int i = 0; i < m; i++) {
            b[i] = (int)Math.pow(2, sc.nextInt());
        }
        RandomizeArray(a);
        RandomizeArray(b);
        Arrays.sort(a);
        Arrays.sort(b);
        int cnt = 0;
        for (int i = 0, j = 0; i < m && j < n; i++) {
            while(j < n && b[i] > a[j])j++;
            if(j < n){
                cnt++;
                a[j] -= b[i];
            }
        }
        wr.println(cnt);
        wr.close();
    }

    static int[] RandomizeArray(int[] array){
        Random rgen = new Random();  // Random number generator

        for (int i=0; i<array.length; i++) {
            int randomPosition = rgen.nextInt(array.length);
            int temp = array[i];
            array[i] = array[randomPosition];
            array[randomPosition] = temp;
        }

        return array;
    }
}

class Scanner
{
    StringTokenizer st;
    BufferedReader br;

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

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

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

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

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

    public double nextDouble() throws IOException
    {
        String x = next();
        StringBuilder sb = new StringBuilder("0");
        double res = 0, f = 1;
        boolean dec = false, neg = false;
        int start = 0;
        if(x.charAt(0) == '-')
        {
            neg = true;
            start++;
        }
        for(int i = start; i < x.length(); i++)
            if(x.charAt(i) == '.')
            {
                res = Long.parseLong(sb.toString());
                sb = new StringBuilder("0");
                dec = true;
            }
            else
            {
                sb.append(x.charAt(i));
                if(dec)
                    f *= 10;
            }
        res += Long.parseLong(sb.toString()) / f;
        return res * (neg?-1:1);
    }

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

}

import java.util.*;
import java.io.*;
import static java.lang.Long.min;
import static java.lang.Long.max;
import static java.lang.Math.abs;
import static java.lang.Math.pow;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
    public class Mamo {
static Reader  in=new Reader ();
static long ans,sum,mx=(long) pow(10,9);
static int []a,b;
static StringBuilder sd=new StringBuilder();
    public static void main(String [] args) {
       int n=in.nextInt(),m=in.nextInt();
       a=new int [31];b=new int [31];
       int w[]=new int [31];
       w[0]=1;
       for(int i=1;i<=30;i++)w[i]=w[i-1]*2;
       for(int i=0;i<n;i++){
       int x=in.nextInt();
       while(x!=0)
       for(int u=0;u<31;u++)
       if(w[u]>x){
       x-=w[u-1];a[u-1]++;break;}
       }

       for(int i=0;i<m;i++){
       int x=in.nextInt();
       if(x<30)b[x]++;
       }

   for(int i=0,u=0;i<=30&&u<=30;){
   while(i!=31&&a[i]==0)i++;
   while(u!=31&&b[u]==0)u++;
   if(i==31||u==31)break;
   if(i==u){int x=a[i];
   ans+=min(a[i],b[u]);
   a[i]=0;
   b[u]=(int) max(0,b[u]-x);
   }
   else if(i<u) {i++;}
   else if(i>u){
   int x=i-u;
   x=(int) pow(2,x);
   while(b[u]>0&&a[i]>0){
       ans+=min(b[u],x);
       b[u]-=x;
   a[i]--;
   }
   if(b[u]<0)b[u]=0;}
   }System.out.println(ans);
    }
   static long gcd(long a,long b){
       if(b==0){return a;}
   return gcd(b,a%b);}
   static class Reader
    {
        private InputStream mIs;private byte[] buf = new byte[1024];private int curChar,numChars;public Reader() { this(System.in); }public Reader(InputStream is) { mIs = is;}
        public int read() {if (numChars == -1) throw new InputMismatchException();if (curChar >= numChars) {curChar = 0;try { numChars = mIs.read(buf);} catch (IOException e) { throw new InputMismatchException();}if (numChars <= 0) return -1; }return buf[curChar++];}
        public String nextLine(){int c = read();while (isSpaceChar(c)) c = read();StringBuilder res = new StringBuilder();do {res.appendCodePoint(c);c = read();}while (!isEndOfLine(c));return res.toString() ;}
        public String s(){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 long l(){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 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 double d() throws IOException {return Double.parseDouble(s()) ;}
        public boolean isSpaceChar(int c) { return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1; }
        public boolean isEndOfLine(int c) { return c == '\n' || c == '\r' || c == -1; }
        public int[] arr(int n){int[] ret = new int[n];for (int i = 0; i < n; i++) {ret[i] = nextInt();}return ret;}
    }

}

class Sorting{

 public static int[] bucketSort(int[] array, int bucketCount) {

 if (bucketCount <= 0) throw new IllegalArgumentException("Invalid bucket count");

 if (array.length <= 1) return array; //trivially sorted

 int high = array[0];

 int low = array[0];

 for (int i = 1; i < array.length; i++) { //find the range of input elements

 if (array[i] > high) high = array[i];

 if (array[i] < low) low = array[i];

 }

 double interval = ((double)(high - low + 1))/bucketCount; //range of one bucket

 ArrayList<Integer> buckets[] = new ArrayList[bucketCount];

 for (int i = 0; i < bucketCount; i++) { //initialize buckets

 buckets[i] = new ArrayList();

 }

 for (int i = 0; i < array.length; i++) { //partition the input array

 buckets[(int)((array[i] - low)/interval)].add(array[i]);

 }

 int pointer = 0;

 for (int i = 0; i < buckets.length; i++) {

 Collections.sort(buckets[i]); //mergeSort

 for (int j = 0; j < buckets[i].size(); j++) { //merge the buckets

 array[pointer] = buckets[i].get(j);

 pointer++;

 }

}

return array;

}

}

import java.util.*;
import java.io.*;
import static java.lang.Long.min;
import static java.lang.Long.max;
import static java.lang.Math.abs;
import static java.lang.Math.pow;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
    public class Mamo {
static Reader  in=new Reader ();
static long ans,sum,mx=(long) pow(10,9);
static int []a,b;
static StringBuilder sd=new StringBuilder();
    public static void main(String [] args) {
       int n=in.nextInt(),m=in.nextInt();
       a=new int [31];b=new int [31];
       int w[]=new int [31];
       w[0]=1;
       for(int i=1;i<=30;i++)w[i]=w[i-1]*2;
       for(int i=0;i<n;i++){
       int x=in.nextInt();
       while(x!=0)
       for(int u=0;u<31;u++)
       if(w[u]>x){
       x-=w[u-1];a[u-1]++;break;}
       }

       for(int i=0;i<m;i++){
       int x=in.nextInt();
       if(x<30)b[x]++;
       }

   for(int i=0,u=0;i<=30&&u<=30;){
   while(i!=31&&a[i]==0)i++;
   while(u!=31&&b[u]==0)u++;
   if(i==31||u==31)break;
   if(i==u){int x=a[i];
   ans+=min(a[i],b[u]);
   a[i]=0;
   b[u]=(int) max(0,b[u]-x);
   }
   else if(i<u) {i++;}
   else if(i>u){
   int x=i-u;
   x=(int) pow(2,x);
   while(b[u]>0&&a[i]>0){
       ans+=min(b[u],x);
       b[u]-=x;a[i]--;
       if(b[u]<0){
           x=b[u]*-1;
           b[u]=0;
           u++;
           for(;u<31;u++){
           if(x<2){u=0;break;}
           if(b[u]>0){
           int o=x;
           ans+=min(x,b[u]);
           x=(int) max(x-b[u],0);
           b[u]=(int) max(0,b[u]-x);
           }
           x/=2;
           }
           }
   }}
   }System.out.println(ans);
    }
   static long gcd(long a,long b){
       if(b==0){return a;}
   return gcd(b,a%b);}
   static class Reader
    {
        private InputStream mIs;private byte[] buf = new byte[1024];private int curChar,numChars;public Reader() { this(System.in); }public Reader(InputStream is) { mIs = is;}
        public int read() {if (numChars == -1) throw new InputMismatchException();if (curChar >= numChars) {curChar = 0;try { numChars = mIs.read(buf);} catch (IOException e) { throw new InputMismatchException();}if (numChars <= 0) return -1; }return buf[curChar++];}
        public String nextLine(){int c = read();while (isSpaceChar(c)) c = read();StringBuilder res = new StringBuilder();do {res.appendCodePoint(c);c = read();}while (!isEndOfLine(c));return res.toString() ;}
        public String s(){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 long l(){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 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 double d() throws IOException {return Double.parseDouble(s()) ;}
        public boolean isSpaceChar(int c) { return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1; }
        public boolean isEndOfLine(int c) { return c == '\n' || c == '\r' || c == -1; }
        public int[] arr(int n){int[] ret = new int[n];for (int i = 0; i < n; i++) {ret[i] = nextInt();}return ret;}
    }

}

class Sorting{

 public static int[] bucketSort(int[] array, int bucketCount) {

 if (bucketCount <= 0) throw new IllegalArgumentException("Invalid bucket count");

 if (array.length <= 1) return array; //trivially sorted

 int high = array[0];

 int low = array[0];

 for (int i = 1; i < array.length; i++) { //find the range of input elements

 if (array[i] > high) high = array[i];

 if (array[i] < low) low = array[i];

 }

 double interval = ((double)(high - low + 1))/bucketCount; //range of one bucket

 ArrayList<Integer> buckets[] = new ArrayList[bucketCount];

 for (int i = 0; i < bucketCount; i++) { //initialize buckets

 buckets[i] = new ArrayList();

 }

 for (int i = 0; i < array.length; i++) { //partition the input array

 buckets[(int)((array[i] - low)/interval)].add(array[i]);

 }

 int pointer = 0;

 for (int i = 0; i < buckets.length; i++) {

 Collections.sort(buckets[i]); //mergeSort

 for (int j = 0; j < buckets[i].size(); j++) { //merge the buckets

 array[pointer] = buckets[i].get(j);

 pointer++;

 }

}

return array;

}

}

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

public class Main {

    public static void main(String[] args) throws Exception {
        IO io ;
        try {
            io = new IO("in.in", null);
        } catch (IOException e) {
            io = new IO(null, null);
        }

        int n = io.getNextInt(),m = io.getNextInt();
        ArrayList<Integer> A = new ArrayList<>(n);
        int [] freq = new int[32];
        for (int i = 0;i < n;i++)
            A.add(io.getNextInt());
        for (int i = 0;i < m;i++)
            freq[io.getNextInt()]++;
        Collections.sort(A);

        int j = 0,i = 0;
        for (int a : A){
            int r = a;
            while (j < 32 && freq[j] == 0) j++;
            while (j < 32 && (1 << j) <= r) {
                r -= 1 << j;
                freq[j]--;
                while (j < 32 && freq[j] == 0) j++;
                i++;
            }
        }
        io.println(i);
        io.close();
    }
    private static final int onebillion7 = 1000000007;
}

class IO{
    private BufferedReader br;
    private StringTokenizer st;
    private PrintWriter writer;
    private String inputFile,outputFile;

    public boolean hasMore() throws IOException{
        if(st != null && st.hasMoreTokens()) return true;
        if(br != null && br.ready()) return true;
        return false;
    }

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

    public String getNextLine() throws FileNotFoundException, IOException{
        return br.readLine().trim();
    }

    public int getNextInt() throws FileNotFoundException, IOException{
        return Integer.parseInt(getNext());
    }
    public long getNextLong() throws FileNotFoundException, IOException{
        return Long.parseLong(getNext());
    }

    public void print(double x,int num_digits) throws  IOException{
        writer.printf("%." + num_digits + "f" ,x);
    }
    public void println(double x,int num_digits) throws  IOException{
        writer.printf("%." + num_digits + "f\n" ,x);
    }
    public void print(Object o) throws  IOException{
        writer.print(o.toString());
    }

    public void println(Object o) throws  IOException{
        writer.println(o.toString());
    }
    public IO(String x,String y) throws FileNotFoundException, IOException{
        inputFile = x;
        outputFile = y;
        if(x != null) br = new BufferedReader(new FileReader(inputFile));
        else br = new BufferedReader(new InputStreamReader(System.in));
        if(y != null) writer = new PrintWriter(new BufferedWriter(new FileWriter(outputFile)));
        else writer = new PrintWriter(new OutputStreamWriter(System.out));
    }

    protected void close() throws IOException{
        br.close();
        writer.close();
    }
    public void outputArr(Object [] A) throws IOException{
        int L = A.length;
        for (int i = 0;i < L;i++) {
            if(i > 0) writer.print(" ");
            writer.print(A[i]);
        }
        writer.print("\n");
    }
}

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

public class C {
	BufferedReader reader;
    StringTokenizer tokenizer;
    PrintWriter out;

    public void shuffleArray(int[] arr) {
        Random rnd = new Random();
        for (int i = arr.length - 1; i >= 0; i--) {
            int pos = rnd.nextInt(i + 1);
            int temp = arr[i];
            arr[i] = arr[pos];
            arr[pos] = temp;
        }
    }
	public void solve() throws IOException {
		int N = nextInt();
		int M = nextInt();
		int[] a = new int[N];
		int[] b = new int[M];
		for(int i = 0; i < N; i++)
			a[i] = nextInt();
		for(int i = 0; i < M; i++)
			b[i] = nextInt();
		shuffleArray(a);
		shuffleArray(b);
		Arrays.sort(a);
		Arrays.sort(b);

		int curA = 0;
		int ans = 0;
		outer: for(int i = 0; i < M; i++){
			int s = (int)Math.pow(2, b[i]);
			while( a[curA] < s ){
				curA++;
				if( curA == N ) break outer;
			}
			ans++;
			a[curA] -= s;
		}
		out.println(ans);
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new C().run();
	}

	public void run() {
        try {
            reader = new BufferedReader(new InputStreamReader(System.in));
            tokenizer = null;
            out = new PrintWriter(System.out);
            solve();
            reader.close();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

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

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

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

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

}

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

public class C {
	BufferedReader reader;
    StringTokenizer tokenizer;
    PrintWriter out;

    public void shuffleArray(int[] arr) {
        Random rnd = new Random();
        for (int i = arr.length - 1; i >= 0; i--) {
            int pos = rnd.nextInt(i + 1);
            int temp = arr[i];
            arr[i] = arr[pos];
            arr[pos] = temp;
        }
    }
	public void solve() throws IOException {
		int max_bit = 30;

		int N = nextInt();
		int M = nextInt();

		int[] space = new int[max_bit+1];
		int[] size = new int[max_bit+1];
		for(int i = 0; i < N; i++){
			int a = nextInt();
			for(int b = 0; b <= max_bit; b++){
				if( (a >> b & 1) == 1 )
					space[b]++;
			}
		}
		for(int i = 0; i < M; i++)
			size[ nextInt() ] ++;

		int ans = 0;
		int cur_space = 0;
		int cur_can = space[cur_space];
		outer: for(int i = 0; i <= max_bit; i++){
			while( size[i] > cur_can ){
				size[i] -= cur_can;
				ans += cur_can;

				cur_space++;
				if( cur_space > max_bit ) break outer;

				cur_can = space[cur_space] * (int)Math.pow(2, cur_space-i);
			}

			cur_can -= size[i];
			ans += size[i];

			cur_can /= 2;
		}
		out.println(ans);
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new C().run();
	}

	public void run() {
        try {
            reader = new BufferedReader(new InputStreamReader(System.in));
            tokenizer = null;
            out = new PrintWriter(System.out);
            solve();
            reader.close();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

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

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

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

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

}

import java.util.Scanner;
import java.io.OutputStream;
import java.io.IOException;
import java.io.PrintWriter;
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;
		Scanner in = new Scanner(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskC solver = new TaskC();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskC {
    int[] a;
    int[] b = new int[23];
    int n;

    boolean ok(int[] c) {
        for (int s : a) {
            for (int i = c.length - 1; i >= 0; --i) {
                int d = Math.min(s >> i, c[i]);
                s -= (d << i);
                c[i] -= d;
            }
        }
        for (int s : c)
            if (s > 0)
                return false;
        return true;
    }

    public void solve(int testNumber, Scanner in, PrintWriter out) {
        n = in.nextInt();
        int m = in.nextInt();
        a = new int[n];
        for (int i = 0; i < n; ++i)
            a[i] = in.nextInt();
        for (int i = 0; i < m; ++i)
            b[in.nextInt()]++;
        int k = b.length - 1;
        int[] c = new int[23];
        for (; k >= 0; --k) {
            System.arraycopy(b, 0, c, 0, k+1);
            if (ok(c))
                break;

        }
        ++k;

        if (k >= b.length) {
            int res = 0;
            for (int s : b)
                res += s;
            out.println(res);
            return;
        }

        int l = 0, r = b[k] + 1;
        while (r > l+1) {
            int mid = l + (r-l)/2;
            System.arraycopy(b, 0, c, 0, k+1);
            c[k] = mid;
            if (ok(c))
                l = mid;
            else
                r = mid;
        }

        int res = 0;
        for (int i = 0; i < k; ++i)
            res += b[i];
        res += l;
        out.println(res);
    }
}

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

import static java.util.Collections.*;
import static java.lang.Math.*;
import static java.util.Arrays.*;
import static java.math.BigInteger.*;
import static java.lang.Character.*;

public class Main {

    void run(){
//        boolean oj = true;
//        boolean oj = false;

        Locale.setDefault(Locale.US);
        boolean oj = System.getProperty("ONLINE_JUDGE")!=null;

        String fileName = oj? "castle" : "dwarf";
        try {
            if( oj ){
                br = new BufferedReader(new InputStreamReader(System.in));
                out = new PrintWriter(new OutputStreamWriter(System.out));
            }
            else{
                br  = new BufferedReader(new FileReader(fileName+".in" ));
                out = new PrintWriter   (new FileWriter(fileName+".out"));
            }
        } catch (Exception e) {
            MLE();
        }
        long tb = System.currentTimeMillis();
        solve();
//        if( !oj )
//            out.println("TIME: " + (System.currentTimeMillis() - tb) / 1e3) ;
        exit(0);
    }

    BufferedReader br;
    StringTokenizer st;
    PrintWriter out;

    String next(){
        while( st==null || !st.hasMoreElements() ){
            try {
                st = new StringTokenizer(br.readLine());
            } catch (IOException e) {
                return null;
            }
        }
        return st.nextToken();
    }
    String nextLine(){
        try {
            return br.readLine();
        } catch (Exception e) {
            return null;
        }
    }
    int nextInt(){ return Integer.parseInt(next()); }
    double nextDouble(){ return Double.parseDouble(next()); }
    long nextLong(){ return Long.parseLong(next()); }

    void exit( int val ){
        out.flush();
        System.exit(val);
    }

    void MLE(){
        int[][] arr = new int[1024*1024][];
        for( int i = 0; i < 1024*1024; ++i )
            arr[i] = new int[1024*1024];
    }

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

    final int maxCnt = 50;
    int n, m;
    int szArr;
    int[] arr;
    int[] cnt;

    boolean isOdd( int v ){ return (v&1)==1; }

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

        szArr = n;
        arr = new int[n];
        for( int i = 0; i < n; ++i )
            arr[i] = nextInt();

        cnt = new int[maxCnt+1];
        for( int i = 0; i < m; ++i )
            ++cnt[nextInt()];

        int[] odd  = new int[n],
               even = new int[n];
        int szOdd, szEven;
        int ans = 0;
        for( int pos = 0; pos <= 33; ++pos ){
            szOdd = szEven = 0;
            for( int i = 0; i < n; ++i ){
                if( isOdd(arr[i]) )
                    odd[szOdd++] = arr[i];
                else
                    even[szEven++] = arr[i];
            }
            while( 0 < szOdd && 0 < cnt[pos] ){
                even[szEven++] = odd[--szOdd] - 1;
                --cnt[pos];
                ++ans;
            }
            cnt[pos+1] += (cnt[pos]+1)>>1;
            szArr = 0;
            for( int i = 0; i < szOdd ; ++i ) arr[szArr++] = odd [i]>>1;
            for( int i = 0; i < szEven; ++i ) arr[szArr++] = even[i]>>1;
            if( szArr != n ) MLE();
        }
        out.println(ans);
    }

    void deb(){
    }

}

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

import static java.util.Collections.*;
import static java.lang.Math.*;
import static java.util.Arrays.*;
import static java.math.BigInteger.*;
import static java.lang.Character.*;

public class Main {

    void run(){
//        boolean oj = true;
//        boolean oj = false;

        Locale.setDefault(Locale.US);
        boolean oj = System.getProperty("ONLINE_JUDGE")!=null;

        String fileName = oj? "castle" : "dwarf";
        try {
            if( oj ){
                br = new BufferedReader(new InputStreamReader(System.in));
                out = new PrintWriter(new OutputStreamWriter(System.out));
            }
            else{
                br  = new BufferedReader(new FileReader(fileName+".in" ));
                out = new PrintWriter   (new FileWriter(fileName+".out"));
            }
        } catch (Exception e) {
            MLE();
        }
        long tb = System.currentTimeMillis();
        solve();
//        if( !oj )
//            out.println("TIME: " + (System.currentTimeMillis() - tb) / 1e3) ;
        exit(0);
    }

    BufferedReader br;
    StringTokenizer st;
    PrintWriter out;

    String next(){
        while( st==null || !st.hasMoreElements() ){
            try {
                st = new StringTokenizer(br.readLine());
            } catch (IOException e) {
                return null;
            }
        }
        return st.nextToken();
    }
    String nextLine(){
        try {
            return br.readLine();
        } catch (Exception e) {
            return null;
        }
    }
    int nextInt(){ return Integer.parseInt(next()); }
    double nextDouble(){ return Double.parseDouble(next()); }
    long nextLong(){ return Long.parseLong(next()); }

    void exit( int val ){
        out.flush();
        System.exit(val);
    }

    void MLE(){
        int[][] arr = new int[1024*1024][];
        for( int i = 0; i < 1024*1024; ++i )
            arr[i] = new int[1024*1024];
    }

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

    final int maxCnt = 31;
    int n, m;
    int szArr;
    int[] arr;
    int[] cnt;

    boolean isOdd( int v ){ return (v&1)==1; }

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

        szArr = n;
        arr = new int[n];
        for( int i = 0; i < n; ++i )
            arr[i] = nextInt();

        cnt = new int[maxCnt+1];
        for( int i = 0; i < m; ++i )
            ++cnt[nextInt()];

        int[] odd = new int[n],
            even = new int[n];
        int szOdd, szEven;
        int ans = 0;
        for( int pos = 0; pos <= maxCnt; ++pos ){
            szOdd = szEven = 0;
            for( int i = 0; i < n; ++i ){
                if( isOdd(arr[i]) )
                    odd[szOdd++] = arr[i];
                else
                    even[szEven++] = arr[i];
            }
            while( 0 < szOdd && 0 < cnt[pos] ){
                even[szEven++] = odd[--szOdd] - 1;
                --cnt[pos];
                ++ans;
            }
            if( pos != maxCnt ) cnt[pos+1] += (cnt[pos]+1)/2;
            szArr = 0;
            for( int i = 0; i < szOdd ; ++i ) arr[szArr++] = odd [i] / 2;
            for( int i = 0; i < szEven; ++i ) arr[szArr++] = even[i] / 2;
            if( szArr != n ) MLE();
        }
        out.println(ans);
    }

    void deb(){
    }

}

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

public class C {

	private void add(int[] p, int a) {
		for (int j = 0; j < 30; j++) {
			if ((a & (1 << j)) != 0) {
				p[j]++;
			}
		}
	}

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

		int[] p = new int[30];
		for (int i = 0; i < n; i++) {
			add(p, nextInt());
		}

		int[] b = new int[30];
		for (int i = 0; i < m; i++) {
			b[nextInt()]++;
		}

		int res = 0;
		for (int i = 0; i < 30; i++) {
			int d = 1;
			for (int j = i; j < 30; j++) {
				if (p[j] * d >= b[i]) {
					res += b[i];
					p[j] -= b[i] / d;
					if (b[i] % d != 0) {
						p[j]--;
						add(p, (1 << j) - (b[i] % d) * (1 << i));
					}
					break;
				} else {
					p[j] = 0;
					b[i] -= p[j] * d;
					res += p[j] * d;
					d *= 2;
				}
			}
		}

		println(res);
	}

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

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

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

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

	private void print(Object o) {
		writer.print(o);
	}

	private void println(Object o) {
		writer.println(o);
	}

	private void printf(String format, Object... o) {
		writer.printf(format, o);
	}

	public static void main(String[] args) {
		long time = System.currentTimeMillis();
		Locale.setDefault(Locale.US);
		new C().run();
		System.err.printf("%.3f\n", 1e-3 * (System.currentTimeMillis() - time));
	}

	BufferedReader reader;
	StringTokenizer tokenizer;
	PrintWriter writer;

	private void run() {
		try {
			reader = new BufferedReader(new InputStreamReader(System.in));
			writer = new PrintWriter(System.out);
			solve();
			reader.close();
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(13);
		}
	}
}