#include "bits/stdc++.h"
#include <cmath>
using namespace std;

#define f first
#define s second

#define pb push_back
#define pp pop_back
#define mp make_pair

#define sz(x) (int)x.size()
#define sqr(x) ((x) * 1ll * (x))
#define all(x) x.begin(), x.end()
#define clr(a,v) memset(a, v, sizeof(a))

#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define per(i, l, r) for (int i = (l); i >= (r); i--)
#define reflex ios_base::sync_with_stdio(false)

#define nl '\n'
#define ioi exit(0);

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const int N= (int)2e5 + 7;
const int inf = (int)1e9 + 7;
const int mod = (int)1e9 + 7;
//const int mod = 1000000007;
const ll linf = (ll)1e18 + 7;

const int dx[] = {-1, 0, 1, 0, 1, -1, -1, 1};
const int dy[] = {0, 1, 0, -1, 1, -1, 1, -1};
const int kx[] = {-1,1,2,2,1,-1,-2,-2};
const int ky[] = {2,2,1,-1,-2,-2,-1,1};

string conv(int a){stringstream ss;ss << a;string str = ss.str();return str;}
string conv(char a){stringstream ss;ss << a;string str = ss.str();return str;}
int conv(string a){stringstream geek(a); int x = 0; geek >> x;   return x;}

struct node 
{ 
   int minimum; 
   int maximum; 
}; 
  

int getMid(int s, int e) {  return s + (e -s)/2;  } 
  
struct node MaxMinUntill(struct node *st, int ss, int se, int qs, 
                         int qe, int index) 
{ 
    
    struct node tmp,left,right; 
    if (qs <= ss && qe >= se) 
        return st[index]; 
  
    
    if (se < qs || ss > qe) 
    { 
       tmp.minimum = INT_MAX; 
       tmp.maximum = INT_MIN; 
       return tmp; 
     } 
  
    int mid = getMid(ss, se); 
    left = MaxMinUntill(st, ss, mid, qs, qe, 2*index+1); 
    right = MaxMinUntill(st, mid+1, se, qs, qe, 2*index+2); 
    tmp.minimum = min(left.minimum, right.minimum); 
    tmp.maximum = max(left.maximum, right.maximum); 
    return tmp; 
} 
  
 
struct node MaxMin(struct node *st, int n, int qs, int qe) 
{ 
    struct node tmp; 
  
    if (qs < 0 || qe > n-1 || qs > qe) 
    { 
        printf("Invalid Input"); 
        tmp.minimum = INT_MIN; 
        tmp.minimum = INT_MAX; 
        return tmp; 
    } 
  
    return MaxMinUntill(st, 0, n-1, qs, qe, 0); 
} 
  
void constructSTUtil(int arr[], int ss, int se, struct node *st, int si) 
{ 
    if (ss == se) 
    { 
        st[si].minimum = arr[ss]; 
        st[si].maximum = arr[ss]; 
        return ; 
    } 
  
    int mid = getMid(ss, se); 
    constructSTUtil(arr, ss, mid, st, si*2+1); 
    constructSTUtil(arr, mid+1, se, st, si*2+2); 
  
    st[si].minimum = min(st[si*2+1].minimum, st[si*2+2].minimum); 
    st[si].maximum = max(st[si*2+1].maximum, st[si*2+2].maximum); 
} 
  
struct node *constructST(int arr[], int n) 
{ 
    int x = (int)(ceil(log2(n))); 
  
    int max_size = 2*(int)pow(2, x) - 1; 
  
    struct node *st = new struct node[max_size]; 
  
    constructSTUtil(arr, 0, n-1, st, 0); 
  
    return st; 
} 


ll gcd(ll a,ll b)
{
    if(a<b)
        swap(a,b);
    return (b==0)?a:gcd(b,a%b);
}

ll lcm (ll a, ll b){
	return a/gcd(a,b)*b;
}


int main()
{ 
	ll a, b , c , d;
	cin>> a >> b >> c >> d;
	ll sumc = b/c - (a-1)/c;
	ll sumb = b/d - (a-1)/d;
	ll x = lcm(c,d);
	ll sumi = b/x - (a-1)/x;
	
	//~ cout<<sumc <<" "<< sumb<<" "<<sumi<<endl;
	
	cout<< b-(a-1) - ((sumc + sumb)- sumi); 
	return 0; 
} 


Measured memory_bytes: 256