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

/******************************\
 * The solution is at the top *
 *                            *
 *   Created by : azhar556    *
\******************************/

public class Main {
	static long Gcd (long c, long d) {
		return c == 0 ? d : Gcd(d % c , c);
	}
	static long Lcm (long c, long d) {
		return c * d / Gcd(c, d);
	}
    static void solve() {
		long A = nl();
		long B = nl();
		long C = nl();
		long D = nl();
		long LcmCD = Lcm(C, D);
		long tot = B - A + 1;
		
		long divC = A / C;
		if (A % C != 0) divC++;
		if (B - (C * divC) >= 0) tot -= (B - (C * divC)) / C + 1;
		err.println(tot);
		
		long divD = A / D;
		if (A % D != 0) divD++;
		if (B - (D * divD) >= 0) tot -= (B - (D * divD)) / D + 1;
		err.println(tot + " " + LcmCD);
		
		long divCD = A / LcmCD;
		if (A % LcmCD != 0) divCD++;
		if (B - (LcmCD * divCD) >= 0) tot += (B - (LcmCD * divCD)) / LcmCD + 1;
		out.println(tot);
    }    

    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        int t;// = ni();
        t = 1;
        while (t-- > 0) solve(); 
        err.println("Time elapsed : " + (System.currentTimeMillis() - time) / 1000F + " s.");
        err.close(); out.close();
    }

	static int[] radixSort(int[] f){ return radixSort(f, f.length); }
	static int[] radixSort(int[] f, int n)
	{
		int[] to = new int[n];
		{
			int[] b = new int[65537];
			for(int i = 0;i < n;i++)b[1+(f[i]&0xffff)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;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 < n;i++)b[1+(f[i]>>>16)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;i++)to[b[f[i]>>>16]++] = f[i];
			int[] d = f; f = to;to = d;
		}
		return f;
	}

    static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
    static PrintWriter err = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.err)));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer token;
    
    static boolean hasMoreTokens () {
        String sample = null;
		try {
			sample = br.readLine();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		return sample == null ? false : true;
    }

    static String ns() {
        while (token == null || !token.hasMoreTokens()) {
            try {
                token = new StringTokenizer(br.readLine());
            }
            catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return token.nextToken();
    }
    static char nc() {
        return Character.valueOf(ns().charAt(0));
    }
    static int ni() {
        return Integer.parseInt(ns());
    }
    static double nd() {
        return Double.parseDouble(ns());
    }
    static long nl() {
        return Long.parseLong(ns());
    }
}
// Collections Arrays Math
// Vector HashSet TreeSet HashMap TreeMap ArrayDeque  import java.io.*; io.* java import java.util.*; util.* java public class Main {
	static long Gcd (long c, long d) {
		return c == 0 ? d : Gcd(d % c , c);
	}
	static long Lcm (long c, long d) {
		return c * d / Gcd(c, d);
	}
    static void solve() {
		long A = nl();
		long B = nl();
		long C = nl();
		long D = nl();
		long LcmCD = Lcm(C, D);
		long tot = B - A + 1;
		
		long divC = A / C;
		if (A % C != 0) divC++;
		if (B - (C * divC) >= 0) tot -= (B - (C * divC)) / C + 1;
		err.println(tot);
		
		long divD = A / D;
		if (A % D != 0) divD++;
		if (B - (D * divD) >= 0) tot -= (B - (D * divD)) / D + 1;
		err.println(tot + " " + LcmCD);
		
		long divCD = A / LcmCD;
		if (A % LcmCD != 0) divCD++;
		if (B - (LcmCD * divCD) >= 0) tot += (B - (LcmCD * divCD)) / LcmCD + 1;
		out.println(tot);
    }    

    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        int t;// = ni();
        t = 1;
        while (t-- > 0) solve(); 
        err.println("Time elapsed : " + (System.currentTimeMillis() - time) / 1000F + " s.");
        err.close(); out.close();
    }

	static int[] radixSort(int[] f){ return radixSort(f, f.length); }
	static int[] radixSort(int[] f, int n)
	{
		int[] to = new int[n];
		{
			int[] b = new int[65537];
			for(int i = 0;i < n;i++)b[1+(f[i]&0xffff)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;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 < n;i++)b[1+(f[i]>>>16)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;i++)to[b[f[i]>>>16]++] = f[i];
			int[] d = f; f = to;to = d;
		}
		return f;
	}

    static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
    static PrintWriter err = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.err)));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer token;
    
    static boolean hasMoreTokens () {
        String sample = null;
		try {
			sample = br.readLine();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		return sample == null ? false : true;
    }

    static String ns() {
        while (token == null || !token.hasMoreTokens()) {
            try {
                token = new StringTokenizer(br.readLine());
            }
            catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return token.nextToken();
    }
    static char nc() {
        return Character.valueOf(ns().charAt(0));
    }
    static int ni() {
        return Integer.parseInt(ns());
    }
    static double nd() {
        return Double.parseDouble(ns());
    }
    static long nl() {
        return Long.parseLong(ns());
    }
} Main static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))); out new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))) static PrintWriter err = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.err))); err new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.err))) static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); br new BufferedReader(new InputStreamReader(System.in)) static StringTokenizer token; token static long Gcd (long c, long d) {
		return c == 0 ? d : Gcd(d % c , c);
	} Gcd {
		return c == 0 ? d : Gcd(d % c , c);
	} return c == 0 ? d : Gcd(d % c , c); c == 0 ? d : Gcd(d % c , c) c == 0 c 0 d Gcd(d % c , c) Gcd d % c d c c long c c long d d static long Lcm (long c, long d) {
		return c * d / Gcd(c, d);
	} Lcm {
		return c * d / Gcd(c, d);
	} return c * d / Gcd(c, d); c * d / Gcd(c, d) c * d c d Gcd(c, d) Gcd c d long c c long d d static void solve() {
		long A = nl();
		long B = nl();
		long C = nl();
		long D = nl();
		long LcmCD = Lcm(C, D);
		long tot = B - A + 1;
		
		long divC = A / C;
		if (A % C != 0) divC++;
		if (B - (C * divC) >= 0) tot -= (B - (C * divC)) / C + 1;
		err.println(tot);
		
		long divD = A / D;
		if (A % D != 0) divD++;
		if (B - (D * divD) >= 0) tot -= (B - (D * divD)) / D + 1;
		err.println(tot + " " + LcmCD);
		
		long divCD = A / LcmCD;
		if (A % LcmCD != 0) divCD++;
		if (B - (LcmCD * divCD) >= 0) tot += (B - (LcmCD * divCD)) / LcmCD + 1;
		out.println(tot);
    } solve {
		long A = nl();
		long B = nl();
		long C = nl();
		long D = nl();
		long LcmCD = Lcm(C, D);
		long tot = B - A + 1;
		
		long divC = A / C;
		if (A % C != 0) divC++;
		if (B - (C * divC) >= 0) tot -= (B - (C * divC)) / C + 1;
		err.println(tot);
		
		long divD = A / D;
		if (A % D != 0) divD++;
		if (B - (D * divD) >= 0) tot -= (B - (D * divD)) / D + 1;
		err.println(tot + " " + LcmCD);
		
		long divCD = A / LcmCD;
		if (A % LcmCD != 0) divCD++;
		if (B - (LcmCD * divCD) >= 0) tot += (B - (LcmCD * divCD)) / LcmCD + 1;
		out.println(tot);
    } long A = nl(); A nl() nl long B = nl(); B nl() nl long C = nl(); C nl() nl long D = nl(); D nl() nl long LcmCD = Lcm(C, D); LcmCD Lcm(C, D) Lcm C D long tot = B - A + 1; tot B - A + 1 B - A B A 1 long divC = A / C; divC A / C A C if (A % C != 0) divC++; A % C != 0 A % C A C 0 divC++ divC if (B - (C * divC) >= 0) tot -= (B - (C * divC)) / C + 1; B - (C * divC) >= 0 B - (C * divC) B (C * divC) C divC 0 tot -= (B - (C * divC)) / C + 1 tot (B - (C * divC)) / C + 1 (B - (C * divC)) / C (B - (C * divC)) B (C * divC) C divC C 1 err.println(tot) err.println err tot long divD = A / D; divD A / D A D if (A % D != 0) divD++; A % D != 0 A % D A D 0 divD++ divD if (B - (D * divD) >= 0) tot -= (B - (D * divD)) / D + 1; B - (D * divD) >= 0 B - (D * divD) B (D * divD) D divD 0 tot -= (B - (D * divD)) / D + 1 tot (B - (D * divD)) / D + 1 (B - (D * divD)) / D (B - (D * divD)) B (D * divD) D divD D 1 err.println(tot + " " + LcmCD) err.println err tot + " " + LcmCD tot + " " + LcmCD tot " " LcmCD long divCD = A / LcmCD; divCD A / LcmCD A LcmCD if (A % LcmCD != 0) divCD++; A % LcmCD != 0 A % LcmCD A LcmCD 0 divCD++ divCD if (B - (LcmCD * divCD) >= 0) tot += (B - (LcmCD * divCD)) / LcmCD + 1; B - (LcmCD * divCD) >= 0 B - (LcmCD * divCD) B (LcmCD * divCD) LcmCD divCD 0 tot += (B - (LcmCD * divCD)) / LcmCD + 1 tot (B - (LcmCD * divCD)) / LcmCD + 1 (B - (LcmCD * divCD)) / LcmCD (B - (LcmCD * divCD)) B (LcmCD * divCD) LcmCD divCD LcmCD 1 out.println(tot) out.println out tot public static void main(String[] args) {
        long time = System.currentTimeMillis();
        int t;// = ni();
        t = 1;
        while (t-- > 0) solve(); 
        err.println("Time elapsed : " + (System.currentTimeMillis() - time) / 1000F + " s.");
        err.close(); out.close();
    } main {
        long time = System.currentTimeMillis();
        int t;// = ni();
        t = 1;
        while (t-- > 0) solve(); 
        err.println("Time elapsed : " + (System.currentTimeMillis() - time) / 1000F + " s.");
        err.close(); out.close();
    } long time = System.currentTimeMillis(); time System.currentTimeMillis() System.currentTimeMillis System int t; t t = 1 t 1 while (t-- > 0) solve(); t-- > 0 t-- t 0 solve() solve err.println("Time elapsed : " + (System.currentTimeMillis() - time) / 1000F + " s.") err.println err "Time elapsed : " + (System.currentTimeMillis() - time) / 1000F + " s." "Time elapsed : " + (System.currentTimeMillis() - time) / 1000F + " s." "Time elapsed : " (System.currentTimeMillis() - time) / 1000F (System.currentTimeMillis() - time) System.currentTimeMillis() System.currentTimeMillis System time 1000F " s." err.close() err.close err out.close() out.close out String[] args args static int[] radixSort(int[] f){ return radixSort(f, f.length); } radixSort { return radixSort(f, f.length); } return radixSort(f, f.length); radixSort(f, f.length) radixSort f f.length f f.length int[] f f static int[] radixSort(int[] f, int n)
	{
		int[] to = new int[n];
		{
			int[] b = new int[65537];
			for(int i = 0;i < n;i++)b[1+(f[i]&0xffff)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;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 < n;i++)b[1+(f[i]>>>16)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;i++)to[b[f[i]>>>16]++] = f[i];
			int[] d = f; f = to;to = d;
		}
		return f;
	} radixSort {
		int[] to = new int[n];
		{
			int[] b = new int[65537];
			for(int i = 0;i < n;i++)b[1+(f[i]&0xffff)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;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 < n;i++)b[1+(f[i]>>>16)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;i++)to[b[f[i]>>>16]++] = f[i];
			int[] d = f; f = to;to = d;
		}
		return f;
	} int[] to = new int[n]; to new int[n] n {
			int[] b = new int[65537];
			for(int i = 0;i < n;i++)b[1+(f[i]&0xffff)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;i++)to[b[f[i]&0xffff]++] = f[i];
			int[] d = f; f = to;to = d;
		} int[] b = new int[65537]; b new int[65537] 65537 for(int i = 0;i < n;i++)b[1+(f[i]&0xffff)]++; int i = 0; int i = 0; i 0 i < n i n i++ i++ i b[1+(f[i]&0xffff)]++; b[1+(f[i]&0xffff)]++ b[1+(f[i]&0xffff)] b 1+(f[i]&0xffff) 1 (f[i]&0xffff) f[i] f i 0xffff for(int i = 1;i <= 65536;i++)b[i]+=b[i-1]; int i = 1; int i = 1; i 1 i <= 65536 i 65536 i++ i++ i b[i]+=b[i-1]; b[i]+=b[i-1] b[i] b i b[i-1] b i-1 i 1 for(int i = 0;i < n;i++)to[b[f[i]&0xffff]++] = f[i]; int i = 0; int i = 0; i 0 i < n i n i++ i++ i to[b[f[i]&0xffff]++] = f[i]; to[b[f[i]&0xffff]++] = f[i] to[b[f[i]&0xffff]++] to b[f[i]&0xffff]++ b[f[i]&0xffff] b f[i]&0xffff f[i] f i 0xffff f[i] f i int[] d = f; d f f = to f to to = d to d {
			int[] b = new int[65537];
			for(int i = 0;i < n;i++)b[1+(f[i]>>>16)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;i++)to[b[f[i]>>>16]++] = f[i];
			int[] d = f; f = to;to = d;
		} int[] b = new int[65537]; b new int[65537] 65537 for(int i = 0;i < n;i++)b[1+(f[i]>>>16)]++; int i = 0; int i = 0; i 0 i < n i n i++ i++ i b[1+(f[i]>>>16)]++; b[1+(f[i]>>>16)]++ b[1+(f[i]>>>16)] b 1+(f[i]>>>16) 1 (f[i]>>>16) f[i] f i 16 for(int i = 1;i <= 65536;i++)b[i]+=b[i-1]; int i = 1; int i = 1; i 1 i <= 65536 i 65536 i++ i++ i b[i]+=b[i-1]; b[i]+=b[i-1] b[i] b i b[i-1] b i-1 i 1 for(int i = 0;i < n;i++)to[b[f[i]>>>16]++] = f[i]; int i = 0; int i = 0; i 0 i < n i n i++ i++ i to[b[f[i]>>>16]++] = f[i]; to[b[f[i]>>>16]++] = f[i] to[b[f[i]>>>16]++] to b[f[i]>>>16]++ b[f[i]>>>16] b f[i]>>>16 f[i] f i 16 f[i] f i int[] d = f; d f f = to f to to = d to d return f; f int[] f f int n n static boolean hasMoreTokens () {
        String sample = null;
		try {
			sample = br.readLine();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		return sample == null ? false : true;
    } hasMoreTokens {
        String sample = null;
		try {
			sample = br.readLine();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		return sample == null ? false : true;
    } String sample = null; sample null try {
			sample = br.readLine();
		}
		catch (IOException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} IOException e {
			e.printStackTrace();
		} e.printStackTrace() e.printStackTrace e {
			sample = br.readLine();
		} sample = br.readLine() sample br.readLine() br.readLine br return sample == null ? false : true; sample == null ? false : true sample == null sample null false true static String ns() {
        while (token == null || !token.hasMoreTokens()) {
            try {
                token = new StringTokenizer(br.readLine());
            }
            catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return token.nextToken();
    } ns {
        while (token == null || !token.hasMoreTokens()) {
            try {
                token = new StringTokenizer(br.readLine());
            }
            catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return token.nextToken();
    } while (token == null || !token.hasMoreTokens()) {
            try {
                token = new StringTokenizer(br.readLine());
            }
            catch (IOException e) {
                throw new RuntimeException(e);
            }
        } token == null || !token.hasMoreTokens() token == null token null !token.hasMoreTokens() token.hasMoreTokens() token.hasMoreTokens token {
            try {
                token = new StringTokenizer(br.readLine());
            }
            catch (IOException e) {
                throw new RuntimeException(e);
            }
        } try {
                token = new StringTokenizer(br.readLine());
            }
            catch (IOException e) {
                throw new RuntimeException(e);
            } catch (IOException e) {
                throw new RuntimeException(e);
            } IOException e {
                throw new RuntimeException(e);
            } throw new RuntimeException(e); new RuntimeException(e) {
                token = new StringTokenizer(br.readLine());
            } token = new StringTokenizer(br.readLine()) token new StringTokenizer(br.readLine()) return token.nextToken(); token.nextToken() token.nextToken token static char nc() {
        return Character.valueOf(ns().charAt(0));
    } nc {
        return Character.valueOf(ns().charAt(0));
    } return Character.valueOf(ns().charAt(0)); Character.valueOf(ns().charAt(0)) Character.valueOf Character ns().charAt(0) ns().charAt ns() ns 0 static int ni() {
        return Integer.parseInt(ns());
    } ni {
        return Integer.parseInt(ns());
    } return Integer.parseInt(ns()); Integer.parseInt(ns()) Integer.parseInt Integer ns() ns static double nd() {
        return Double.parseDouble(ns());
    } nd {
        return Double.parseDouble(ns());
    } return Double.parseDouble(ns()); Double.parseDouble(ns()) Double.parseDouble Double ns() ns static long nl() {
        return Long.parseLong(ns());
    } nl {
        return Long.parseLong(ns());
    } return Long.parseLong(ns()); Long.parseLong(ns()) Long.parseLong Long ns() ns public class Main {
	static long Gcd (long c, long d) {
		return c == 0 ? d : Gcd(d % c , c);
	}
	static long Lcm (long c, long d) {
		return c * d / Gcd(c, d);
	}
    static void solve() {
		long A = nl();
		long B = nl();
		long C = nl();
		long D = nl();
		long LcmCD = Lcm(C, D);
		long tot = B - A + 1;
		
		long divC = A / C;
		if (A % C != 0) divC++;
		if (B - (C * divC) >= 0) tot -= (B - (C * divC)) / C + 1;
		err.println(tot);
		
		long divD = A / D;
		if (A % D != 0) divD++;
		if (B - (D * divD) >= 0) tot -= (B - (D * divD)) / D + 1;
		err.println(tot + " " + LcmCD);
		
		long divCD = A / LcmCD;
		if (A % LcmCD != 0) divCD++;
		if (B - (LcmCD * divCD) >= 0) tot += (B - (LcmCD * divCD)) / LcmCD + 1;
		out.println(tot);
    }    

    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        int t;// = ni();
        t = 1;
        while (t-- > 0) solve(); 
        err.println("Time elapsed : " + (System.currentTimeMillis() - time) / 1000F + " s.");
        err.close(); out.close();
    }

	static int[] radixSort(int[] f){ return radixSort(f, f.length); }
	static int[] radixSort(int[] f, int n)
	{
		int[] to = new int[n];
		{
			int[] b = new int[65537];
			for(int i = 0;i < n;i++)b[1+(f[i]&0xffff)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;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 < n;i++)b[1+(f[i]>>>16)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;i++)to[b[f[i]>>>16]++] = f[i];
			int[] d = f; f = to;to = d;
		}
		return f;
	}

    static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
    static PrintWriter err = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.err)));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer token;
    
    static boolean hasMoreTokens () {
        String sample = null;
		try {
			sample = br.readLine();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		return sample == null ? false : true;
    }

    static String ns() {
        while (token == null || !token.hasMoreTokens()) {
            try {
                token = new StringTokenizer(br.readLine());
            }
            catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return token.nextToken();
    }
    static char nc() {
        return Character.valueOf(ns().charAt(0));
    }
    static int ni() {
        return Integer.parseInt(ns());
    }
    static double nd() {
        return Double.parseDouble(ns());
    }
    static long nl() {
        return Long.parseLong(ns());
    }
} public class Main {
	static long Gcd (long c, long d) {
		return c == 0 ? d : Gcd(d % c , c);
	}
	static long Lcm (long c, long d) {
		return c * d / Gcd(c, d);
	}
    static void solve() {
		long A = nl();
		long B = nl();
		long C = nl();
		long D = nl();
		long LcmCD = Lcm(C, D);
		long tot = B - A + 1;
		
		long divC = A / C;
		if (A % C != 0) divC++;
		if (B - (C * divC) >= 0) tot -= (B - (C * divC)) / C + 1;
		err.println(tot);
		
		long divD = A / D;
		if (A % D != 0) divD++;
		if (B - (D * divD) >= 0) tot -= (B - (D * divD)) / D + 1;
		err.println(tot + " " + LcmCD);
		
		long divCD = A / LcmCD;
		if (A % LcmCD != 0) divCD++;
		if (B - (LcmCD * divCD) >= 0) tot += (B - (LcmCD * divCD)) / LcmCD + 1;
		out.println(tot);
    }    

    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        int t;// = ni();
        t = 1;
        while (t-- > 0) solve(); 
        err.println("Time elapsed : " + (System.currentTimeMillis() - time) / 1000F + " s.");
        err.close(); out.close();
    }

	static int[] radixSort(int[] f){ return radixSort(f, f.length); }
	static int[] radixSort(int[] f, int n)
	{
		int[] to = new int[n];
		{
			int[] b = new int[65537];
			for(int i = 0;i < n;i++)b[1+(f[i]&0xffff)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;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 < n;i++)b[1+(f[i]>>>16)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;i++)to[b[f[i]>>>16]++] = f[i];
			int[] d = f; f = to;to = d;
		}
		return f;
	}

    static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
    static PrintWriter err = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.err)));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer token;
    
    static boolean hasMoreTokens () {
        String sample = null;
		try {
			sample = br.readLine();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		return sample == null ? false : true;
    }

    static String ns() {
        while (token == null || !token.hasMoreTokens()) {
            try {
                token = new StringTokenizer(br.readLine());
            }
            catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return token.nextToken();
    }
    static char nc() {
        return Character.valueOf(ns().charAt(0));
    }
    static int ni() {
        return Integer.parseInt(ns());
    }
    static double nd() {
        return Double.parseDouble(ns());
    }
    static long nl() {
        return Long.parseLong(ns());
    }
} Main
import java.io.*;
import java.util.*;

/******************************\
 * The solution is at the top *
 *                            *
 *   Created by : azhar556    *
\******************************/

public class Main {
	static long Gcd (long c, long d) {
		return c == 0 ? d : Gcd(d % c , c);
	}
	static long Lcm (long c, long d) {
		return c * d / Gcd(c, d);
	}
    static void solve() {
		long A = nl();
		long B = nl();
		long C = nl();
		long D = nl();
		long LcmCD = Lcm(C, D);
		long tot = B - A + 1;
		
		long divC = A / C;
		if (A % C != 0) divC++;
		if (B - (C * divC) >= 0) tot -= (B - (C * divC)) / C + 1;
		err.println(tot);
		
		long divD = A / D;
		if (A % D != 0) divD++;
		if (B - (D * divD) >= 0) tot -= (B - (D * divD)) / D + 1;
		err.println(tot + " " + LcmCD);
		
		long divCD = A / LcmCD;
		if (A % LcmCD != 0) divCD++;
		if (B - (LcmCD * divCD) >= 0) tot += (B - (LcmCD * divCD)) / LcmCD + 1;
		out.println(tot);
    }    

    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        int t;// = ni();
        t = 1;
        while (t-- > 0) solve(); 
        err.println("Time elapsed : " + (System.currentTimeMillis() - time) / 1000F + " s.");
        err.close(); out.close();
    }

	static int[] radixSort(int[] f){ return radixSort(f, f.length); }
	static int[] radixSort(int[] f, int n)
	{
		int[] to = new int[n];
		{
			int[] b = new int[65537];
			for(int i = 0;i < n;i++)b[1+(f[i]&0xffff)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;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 < n;i++)b[1+(f[i]>>>16)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;i++)to[b[f[i]>>>16]++] = f[i];
			int[] d = f; f = to;to = d;
		}
		return f;
	}

    static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
    static PrintWriter err = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.err)));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer token;
    
    static boolean hasMoreTokens () {
        String sample = null;
		try {
			sample = br.readLine();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		return sample == null ? false : true;
    }

    static String ns() {
        while (token == null || !token.hasMoreTokens()) {
            try {
                token = new StringTokenizer(br.readLine());
            }
            catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return token.nextToken();
    }
    static char nc() {
        return Character.valueOf(ns().charAt(0));
    }
    static int ni() {
        return Integer.parseInt(ns());
    }
    static double nd() {
        return Double.parseDouble(ns());
    }
    static long nl() {
        return Long.parseLong(ns());
    }
}
// Collections Arrays Math
// Vector HashSet TreeSet HashMap TreeMap ArrayDeque 