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

import static java.lang.Math.*;

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

  private void solve() {
    try(InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out)) {

      long a = in.nextLong();
      long b = in.nextLong();
      long c = in.nextLong();
      long d = in.nextLong();

      final long lcm = c * d / gcd(c ,d);

      a--;
      long x = (b / c) - (a / c);
      long y = (b / d) - (a / d);
      long z = (b / lcm) - (a / lcm);

      final long ans = (b - a) - x - y + z;
      out.println(ans);
    }
    catch(IOException e) {
      System.err.println(e);
    }
  }

  // def gcd(a:Long, b:Long):Long = {
  //   if(b == 0) a
  //   else gcd(b, a%b)
  // }

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

  int atoi(String s) { return Integer.parseInt(s); }
  long atol(String s) { return Long.parseLong(s); }

  static class InputReader implements AutoCloseable {
    public BufferedReader br;
    public StringTokenizer st;

    public InputReader(InputStream stream) {
      br = new BufferedReader(new InputStreamReader(stream), 32768);
      st = null;
    }
    public String next() {
      if (st == null || !st.hasMoreTokens()) {
        try { st = new StringTokenizer(br.readLine());
        } catch (IOException e) {
          throw new UncheckedIOException(e);
        }
      }
      return st.nextToken();
    }
    public int nextInt() { return Integer.parseInt(next()); }
    public long nextLong() { return Long.parseLong(next()); }
    int[] mapInt(int len) {
      int[] ret = new int[len];
      for (int i = 0; i < len; i++) ret[i] = Integer.parseInt(next());
      return ret;
    }
    long[] mapLong(int len) {
      long[] ret = new long[len];
      for (int i = 0; i < len; i++) ret[i] = Long.parseLong(next());
      return ret;
    }
    @Override public void close() throws IOException { br.close(); }
  }
} import java.io.*; io.* java import java.util.StringTokenizer; StringTokenizer java.util import static java.lang.Math.*; import static java.lang.Math.*; import static java.lang.Math.*; public class Main {
  public static void main(String[] args) {
    new Main().solve();
  }

  private void solve() {
    try(InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out)) {

      long a = in.nextLong();
      long b = in.nextLong();
      long c = in.nextLong();
      long d = in.nextLong();

      final long lcm = c * d / gcd(c ,d);

      a--;
      long x = (b / c) - (a / c);
      long y = (b / d) - (a / d);
      long z = (b / lcm) - (a / lcm);

      final long ans = (b - a) - x - y + z;
      out.println(ans);
    }
    catch(IOException e) {
      System.err.println(e);
    }
  }

  // def gcd(a:Long, b:Long):Long = {
  //   if(b == 0) a
  //   else gcd(b, a%b)
  // }

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

  int atoi(String s) { return Integer.parseInt(s); }
  long atol(String s) { return Long.parseLong(s); }

  static class InputReader implements AutoCloseable {
    public BufferedReader br;
    public StringTokenizer st;

    public InputReader(InputStream stream) {
      br = new BufferedReader(new InputStreamReader(stream), 32768);
      st = null;
    }
    public String next() {
      if (st == null || !st.hasMoreTokens()) {
        try { st = new StringTokenizer(br.readLine());
        } catch (IOException e) {
          throw new UncheckedIOException(e);
        }
      }
      return st.nextToken();
    }
    public int nextInt() { return Integer.parseInt(next()); }
    public long nextLong() { return Long.parseLong(next()); }
    int[] mapInt(int len) {
      int[] ret = new int[len];
      for (int i = 0; i < len; i++) ret[i] = Integer.parseInt(next());
      return ret;
    }
    long[] mapLong(int len) {
      long[] ret = new long[len];
      for (int i = 0; i < len; i++) ret[i] = Long.parseLong(next());
      return ret;
    }
    @Override public void close() throws IOException { br.close(); }
  }
} Main public static void main(String[] args) {
    new Main().solve();
  } main {
    new Main().solve();
  } new Main().solve() new Main().solve new Main() String[] args args private void solve() {
    try(InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out)) {

      long a = in.nextLong();
      long b = in.nextLong();
      long c = in.nextLong();
      long d = in.nextLong();

      final long lcm = c * d / gcd(c ,d);

      a--;
      long x = (b / c) - (a / c);
      long y = (b / d) - (a / d);
      long z = (b / lcm) - (a / lcm);

      final long ans = (b - a) - x - y + z;
      out.println(ans);
    }
    catch(IOException e) {
      System.err.println(e);
    }
  } solve {
    try(InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out)) {

      long a = in.nextLong();
      long b = in.nextLong();
      long c = in.nextLong();
      long d = in.nextLong();

      final long lcm = c * d / gcd(c ,d);

      a--;
      long x = (b / c) - (a / c);
      long y = (b / d) - (a / d);
      long z = (b / lcm) - (a / lcm);

      final long ans = (b - a) - x - y + z;
      out.println(ans);
    }
    catch(IOException e) {
      System.err.println(e);
    }
  } try(InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out)) {

      long a = in.nextLong();
      long b = in.nextLong();
      long c = in.nextLong();
      long d = in.nextLong();

      final long lcm = c * d / gcd(c ,d);

      a--;
      long x = (b / c) - (a / c);
      long y = (b / d) - (a / d);
      long z = (b / lcm) - (a / lcm);

      final long ans = (b - a) - x - y + z;
      out.println(ans);
    }
    catch(IOException e) {
      System.err.println(e);
    } catch(IOException e) {
      System.err.println(e);
    } IOException e {
      System.err.println(e);
    } System.err.println(e) System.err.println System.err System System.err e {

      long a = in.nextLong();
      long b = in.nextLong();
      long c = in.nextLong();
      long d = in.nextLong();

      final long lcm = c * d / gcd(c ,d);

      a--;
      long x = (b / c) - (a / c);
      long y = (b / d) - (a / d);
      long z = (b / lcm) - (a / lcm);

      final long ans = (b - a) - x - y + z;
      out.println(ans);
    } InputReader in = new InputReader(System.in) InputReader in = new InputReader(System.in) new InputReader(System.in) PrintWriter out = new PrintWriter(System.out) PrintWriter out = new PrintWriter(System.out) new PrintWriter(System.out) long a = in.nextLong(); a in.nextLong() in.nextLong in long b = in.nextLong(); b in.nextLong() in.nextLong in long c = in.nextLong(); c in.nextLong() in.nextLong in long d = in.nextLong(); d in.nextLong() in.nextLong in final long lcm = c * d / gcd(c ,d); lcm c * d / gcd(c ,d) c * d c d gcd(c ,d) gcd c d a-- a long x = (b / c) - (a / c); x (b / c) - (a / c) (b / c) b c (a / c) a c long y = (b / d) - (a / d); y (b / d) - (a / d) (b / d) b d (a / d) a d long z = (b / lcm) - (a / lcm); z (b / lcm) - (a / lcm) (b / lcm) b lcm (a / lcm) a lcm final long ans = (b - a) - x - y + z; ans (b - a) - x - y + z (b - a) - x - y (b - a) - x - y (b - a) b a x y z out.println(ans) out.println out ans long gcd(long a, long b) {
    if(b == 0) return a;
    return gcd(b, a % b);
  } gcd {
    if(b == 0) return a;
    return gcd(b, a % b);
  } if(b == 0) return a; b == 0 b 0 return a; a return gcd(b, a % b); gcd(b, a % b) gcd b a % b a b long a a long b b int atoi(String s) { return Integer.parseInt(s); } atoi { return Integer.parseInt(s); } return Integer.parseInt(s); Integer.parseInt(s) Integer.parseInt Integer s String s s long atol(String s) { return Long.parseLong(s); } atol { return Long.parseLong(s); } return Long.parseLong(s); Long.parseLong(s) Long.parseLong Long s String s s static class InputReader implements AutoCloseable {
    public BufferedReader br;
    public StringTokenizer st;

    public InputReader(InputStream stream) {
      br = new BufferedReader(new InputStreamReader(stream), 32768);
      st = null;
    }
    public String next() {
      if (st == null || !st.hasMoreTokens()) {
        try { st = new StringTokenizer(br.readLine());
        } catch (IOException e) {
          throw new UncheckedIOException(e);
        }
      }
      return st.nextToken();
    }
    public int nextInt() { return Integer.parseInt(next()); }
    public long nextLong() { return Long.parseLong(next()); }
    int[] mapInt(int len) {
      int[] ret = new int[len];
      for (int i = 0; i < len; i++) ret[i] = Integer.parseInt(next());
      return ret;
    }
    long[] mapLong(int len) {
      long[] ret = new long[len];
      for (int i = 0; i < len; i++) ret[i] = Long.parseLong(next());
      return ret;
    }
    @Override public void close() throws IOException { br.close(); }
  } InputReader public BufferedReader br; br public StringTokenizer st; st public InputReader(InputStream stream) {
      br = new BufferedReader(new InputStreamReader(stream), 32768);
      st = null;
    } InputReader {
      br = new BufferedReader(new InputStreamReader(stream), 32768);
      st = null;
    } br = new BufferedReader(new InputStreamReader(stream), 32768) br new BufferedReader(new InputStreamReader(stream), 32768) st = null st null InputStream stream stream public String next() {
      if (st == null || !st.hasMoreTokens()) {
        try { st = new StringTokenizer(br.readLine());
        } catch (IOException e) {
          throw new UncheckedIOException(e);
        }
      }
      return st.nextToken();
    } next {
      if (st == null || !st.hasMoreTokens()) {
        try { st = new StringTokenizer(br.readLine());
        } catch (IOException e) {
          throw new UncheckedIOException(e);
        }
      }
      return st.nextToken();
    } if (st == null || !st.hasMoreTokens()) {
        try { st = new StringTokenizer(br.readLine());
        } catch (IOException e) {
          throw new UncheckedIOException(e);
        }
      } st == null || !st.hasMoreTokens() st == null st null !st.hasMoreTokens() st.hasMoreTokens() st.hasMoreTokens st {
        try { st = new StringTokenizer(br.readLine());
        } catch (IOException e) {
          throw new UncheckedIOException(e);
        }
      } try { st = new StringTokenizer(br.readLine());
        } catch (IOException e) {
          throw new UncheckedIOException(e);
        } catch (IOException e) {
          throw new UncheckedIOException(e);
        } IOException e {
          throw new UncheckedIOException(e);
        } throw new UncheckedIOException(e); new UncheckedIOException(e) { st = new StringTokenizer(br.readLine());
        } st = new StringTokenizer(br.readLine()) st new StringTokenizer(br.readLine()) return st.nextToken(); st.nextToken() st.nextToken st public int nextInt() { return Integer.parseInt(next()); } nextInt { return Integer.parseInt(next()); } return Integer.parseInt(next()); Integer.parseInt(next()) Integer.parseInt Integer next() next public long nextLong() { return Long.parseLong(next()); } nextLong { return Long.parseLong(next()); } return Long.parseLong(next()); Long.parseLong(next()) Long.parseLong Long next() next int[] mapInt(int len) {
      int[] ret = new int[len];
      for (int i = 0; i < len; i++) ret[i] = Integer.parseInt(next());
      return ret;
    } mapInt {
      int[] ret = new int[len];
      for (int i = 0; i < len; i++) ret[i] = Integer.parseInt(next());
      return ret;
    } int[] ret = new int[len]; ret new int[len] len for (int i = 0; i < len; i++) ret[i] = Integer.parseInt(next()); int i = 0; int i = 0; i 0 i < len i len i++ i++ i ret[i] = Integer.parseInt(next()); ret[i] = Integer.parseInt(next()) ret[i] ret i Integer.parseInt(next()) Integer.parseInt Integer next() next return ret; ret int len len long[] mapLong(int len) {
      long[] ret = new long[len];
      for (int i = 0; i < len; i++) ret[i] = Long.parseLong(next());
      return ret;
    } mapLong {
      long[] ret = new long[len];
      for (int i = 0; i < len; i++) ret[i] = Long.parseLong(next());
      return ret;
    } long[] ret = new long[len]; ret new long[len] len for (int i = 0; i < len; i++) ret[i] = Long.parseLong(next()); int i = 0; int i = 0; i 0 i < len i len i++ i++ i ret[i] = Long.parseLong(next()); ret[i] = Long.parseLong(next()) ret[i] ret i Long.parseLong(next()) Long.parseLong Long next() next return ret; ret int len len @Override public void close() throws IOException { br.close(); } close { br.close(); } br.close() br.close br AutoCloseable public class Main {
  public static void main(String[] args) {
    new Main().solve();
  }

  private void solve() {
    try(InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out)) {

      long a = in.nextLong();
      long b = in.nextLong();
      long c = in.nextLong();
      long d = in.nextLong();

      final long lcm = c * d / gcd(c ,d);

      a--;
      long x = (b / c) - (a / c);
      long y = (b / d) - (a / d);
      long z = (b / lcm) - (a / lcm);

      final long ans = (b - a) - x - y + z;
      out.println(ans);
    }
    catch(IOException e) {
      System.err.println(e);
    }
  }

  // def gcd(a:Long, b:Long):Long = {
  //   if(b == 0) a
  //   else gcd(b, a%b)
  // }

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

  int atoi(String s) { return Integer.parseInt(s); }
  long atol(String s) { return Long.parseLong(s); }

  static class InputReader implements AutoCloseable {
    public BufferedReader br;
    public StringTokenizer st;

    public InputReader(InputStream stream) {
      br = new BufferedReader(new InputStreamReader(stream), 32768);
      st = null;
    }
    public String next() {
      if (st == null || !st.hasMoreTokens()) {
        try { st = new StringTokenizer(br.readLine());
        } catch (IOException e) {
          throw new UncheckedIOException(e);
        }
      }
      return st.nextToken();
    }
    public int nextInt() { return Integer.parseInt(next()); }
    public long nextLong() { return Long.parseLong(next()); }
    int[] mapInt(int len) {
      int[] ret = new int[len];
      for (int i = 0; i < len; i++) ret[i] = Integer.parseInt(next());
      return ret;
    }
    long[] mapLong(int len) {
      long[] ret = new long[len];
      for (int i = 0; i < len; i++) ret[i] = Long.parseLong(next());
      return ret;
    }
    @Override public void close() throws IOException { br.close(); }
  }
} public class Main {
  public static void main(String[] args) {
    new Main().solve();
  }

  private void solve() {
    try(InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out)) {

      long a = in.nextLong();
      long b = in.nextLong();
      long c = in.nextLong();
      long d = in.nextLong();

      final long lcm = c * d / gcd(c ,d);

      a--;
      long x = (b / c) - (a / c);
      long y = (b / d) - (a / d);
      long z = (b / lcm) - (a / lcm);

      final long ans = (b - a) - x - y + z;
      out.println(ans);
    }
    catch(IOException e) {
      System.err.println(e);
    }
  }

  // def gcd(a:Long, b:Long):Long = {
  //   if(b == 0) a
  //   else gcd(b, a%b)
  // }

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

  int atoi(String s) { return Integer.parseInt(s); }
  long atol(String s) { return Long.parseLong(s); }

  static class InputReader implements AutoCloseable {
    public BufferedReader br;
    public StringTokenizer st;

    public InputReader(InputStream stream) {
      br = new BufferedReader(new InputStreamReader(stream), 32768);
      st = null;
    }
    public String next() {
      if (st == null || !st.hasMoreTokens()) {
        try { st = new StringTokenizer(br.readLine());
        } catch (IOException e) {
          throw new UncheckedIOException(e);
        }
      }
      return st.nextToken();
    }
    public int nextInt() { return Integer.parseInt(next()); }
    public long nextLong() { return Long.parseLong(next()); }
    int[] mapInt(int len) {
      int[] ret = new int[len];
      for (int i = 0; i < len; i++) ret[i] = Integer.parseInt(next());
      return ret;
    }
    long[] mapLong(int len) {
      long[] ret = new long[len];
      for (int i = 0; i < len; i++) ret[i] = Long.parseLong(next());
      return ret;
    }
    @Override public void close() throws IOException { br.close(); }
  }
} Main
import java.io.*;
import java.util.StringTokenizer;

import static java.lang.Math.*;

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

  private void solve() {
    try(InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out)) {

      long a = in.nextLong();
      long b = in.nextLong();
      long c = in.nextLong();
      long d = in.nextLong();

      final long lcm = c * d / gcd(c ,d);

      a--;
      long x = (b / c) - (a / c);
      long y = (b / d) - (a / d);
      long z = (b / lcm) - (a / lcm);

      final long ans = (b - a) - x - y + z;
      out.println(ans);
    }
    catch(IOException e) {
      System.err.println(e);
    }
  }

  // def gcd(a:Long, b:Long):Long = {
  //   if(b == 0) a
  //   else gcd(b, a%b)
  // }

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

  int atoi(String s) { return Integer.parseInt(s); }
  long atol(String s) { return Long.parseLong(s); }

  static class InputReader implements AutoCloseable {
    public BufferedReader br;
    public StringTokenizer st;

    public InputReader(InputStream stream) {
      br = new BufferedReader(new InputStreamReader(stream), 32768);
      st = null;
    }
    public String next() {
      if (st == null || !st.hasMoreTokens()) {
        try { st = new StringTokenizer(br.readLine());
        } catch (IOException e) {
          throw new UncheckedIOException(e);
        }
      }
      return st.nextToken();
    }
    public int nextInt() { return Integer.parseInt(next()); }
    public long nextLong() { return Long.parseLong(next()); }
    int[] mapInt(int len) {
      int[] ret = new int[len];
      for (int i = 0; i < len; i++) ret[i] = Integer.parseInt(next());
      return ret;
    }
    long[] mapLong(int len) {
      long[] ret = new long[len];
      for (int i = 0; i < len; i++) ret[i] = Long.parseLong(next());
      return ret;
    }
    @Override public void close() throws IOException { br.close(); }
  }
}