You get to work and turn on the computer. You start coding and give little thought to the RAM role in the whole process. In this problem your task is to solve one of the problems you encounter in your computer routine.We'll consider the RAM as a sequence of cells that can contain data. Some cells already contain some data, some are empty. The empty cells form the so-called memory clusters. Thus, a memory cluster is a sequence of some consecutive empty memory cells. You have exactly n memory clusters, the i-th cluster consists of ai cells. You need to find memory for m arrays in your program. The j-th array takes 2bj consecutive memory cells. There possibly isn't enough memory for all m arrays, so your task is to determine what maximum number of arrays can be located in the available memory clusters. Of course, the arrays cannot be divided between the memory clusters. Also, no cell can belong to two arrays.

The first line of the input contains two integers n and m (1 ≤ n, m ≤ 106). The next line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 109). The next line contains m integers b1, b2, ..., bm (1 ≤ 2bi ≤ 109).

Print a single integer — the answer to the problem.

NoteIn the first example you are given memory clusters with sizes 8, 4, 3, 2, 2 and arrays with sizes 8, 4, 4. There are few ways to obtain an answer equals 2: you can locate array with size 8 to the cluster with size 8, and one of the arrays with size 4 to the cluster with size 4. Another way is to locate two arrays with size 4 to the one cluster with size 8.In the second example you are given 10 memory clusters with size 1 and 6 arrays with size 1. You can choose any 6 clusters and locate all given arrays to them.

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.*;

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

}

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

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.*;
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.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];
	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.*;

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