/**
 * ******* Created  on 10/12/19 1:36 AM*******
 */

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

public class B482 implements Runnable {

    private static final int MAX = (int) (1E5 + 5);
    private static final int MOD = (int) (1E9 + 7);
    private static final long Inf = (int) (1E16 + 10);

    private void solve() throws IOException {
        long cnt1 = reader.nextLong();
        long cnt2 = reader.nextLong();
        long x = reader.nextLong();
        long y = reader.nextLong();

        long l = 0, r = 100;
        long ans = Inf;
        while(l <=r){
            long mid = (l+r)>>1;
            long cnt =  mid / (x*y);
            long blockA = mid/x ;
            long blockB = mid/y;
            long f = cnt1 - blockB + cnt;
            f = Math.max(f, 0);
            long s = cnt2 - blockA + cnt;
            s = Math.max(s, 0);
            if(f +s <= mid - blockA - blockB + cnt){
                ans = mid;
                r = mid-1;
            }else
                l =mid+1;
        }
        writer.print(ans);
    }

    public static void main(String[] args) throws IOException {
        try (Input reader = new StandardInput(); PrintWriter writer = new PrintWriter(System.out)) {
            new B482().run();
        }
    }

    StandardInput reader;
    PrintWriter writer;

    @Override
    public void run() {
        try {
            reader = new StandardInput();
            writer = new PrintWriter(System.out);
            solve();
            reader.close();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    interface Input extends Closeable {
        String next() throws IOException;

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

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

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

        default int[] readIntArray() throws IOException {
            return readIntArray(nextInt());
        }

        default int[] readIntArray(int size) throws IOException {
            int[] array = new int[size];
            for (int i = 0; i < array.length; i++) {
                array[i] = nextInt();
            }
            return array;
        }

        default long[] readLongArray(int size) throws IOException {
            long[] array = new long[size];
            for (int i = 0; i < array.length; i++) {
                array[i] = nextLong();
            }
            return array;
        }
    }

    private static class StandardInput implements Input {
        private final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        private StringTokenizer stringTokenizer;

        @Override
        public void close() throws IOException {
            reader.close();
        }

        @Override
        public String next() throws IOException {
            if (stringTokenizer == null || !stringTokenizer.hasMoreTokens()) {
                stringTokenizer = new StringTokenizer(reader.readLine());
            }
            return stringTokenizer.nextToken();
        }
    }
}
