jiahuimbzuai/CoQuIR huggingface dataset:
//  [ruby]
n, m, k = gets.split.map(&:to_i)
a_arr = gets.split.map(&:to_i)
b_arr = gets.split.map(&:to_i)

sum = 0
sum_a_arr = []
a_arr.each_with_index do |num, i|
  sum += num
  sum_a_arr << [sum, i + 1]
end

sum = 0
sum_b_arr = []
b_arr.each_with_index do |num, i|
  sum += num
  sum_b_arr << [sum, i + 1]
end

max = 0
ind = 0
sum_a_arr.reverse_each do |num, count|
  next if num > k
  
  c = count
  while ind < b_arr.length
    num2, count2 = sum_b_arr[ind]
    break if num + num2 > k

    ind += 1
    c = count + count2
  end
  
  max = c if max < c
end

p max
//  [rust]
fn main() {
    let input: Vec<i32> = read_vec();
    let k = input[2];

    // それぞれの山から読むことのできるところまでを取る
    let a: Vec<i32> = take_by_time(k, &read_vec());
    let b: Vec<i32> = take_by_time(k, &read_vec());

    println!("{}", max_read(k, &a, &b));
}

fn read<T: std::str::FromStr>() -> T {
    let mut buf = String::new();
    std::io::stdin().read_line(&mut buf).ok();
    buf.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>()
        .split_whitespace()
        .map(|s| s.parse().ok().unwrap())
        .collect()
}

fn take_by_time(k: i32, books: &[i32]) -> Vec<i32> {
    let mut v = vec![0];
    books
        .iter()
        .scan(0, |state, cur| {
            if k - *state - cur < 0 {
                return None;
            }

            *state += cur;
            Some(*state)
        })
        .for_each(|n| v.push(n));
    v
}

fn max_read(k: i32, a: &[i32], b: &[i32]) -> i32 {
    let mut ans: i32 = 0;
    let mut j = b.len() - 1;

    a.iter().enumerate().for_each(|(i, &a)| {
        while b[j] > k - a {
            j -= 1;
        }

        ans = ans.max((i + j) as i32);
    });

    ans
}
//  [rust]
use proconio::input;

fn main() {
    input!(n: usize, m: usize, k: u64, a: [u64; n], b: [u64; m]);

    let ans = (0..=n)
        .scan((m, b.iter().sum::<u64>()), |(j, time), i| {
            while *time > k && *j > 0 {
                *j -= 1;
                *time -= b[*j];
            }
            let ret = if *time > k { None } else { Some(i + *j) };
            if i < n {
                *time += a[i];
            }
            ret
        })
        .max()
        .unwrap_or(0);

    println!("{}", ans);
}
//  [rust]
#![allow(clippy::needless_range_loop)]

macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        #[allow(unused_mut)]
        let mut s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};

    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };

    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };

    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };

    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };

    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

fn main() {
    input! {
        n: usize,
        m: usize,
        k: usize,
        a: [usize; n],
        b: [usize; m],
    };

    let mut sum: usize = a.iter().sum();
    let mut ans: usize = 0;
    let mut b_index: usize = 0;
    for a_index in (0..=n).rev() {
        if a_index != n {
            sum -= a[a_index];
        }

        while b_index < m && sum + b[b_index] <= k {
            sum += b[b_index];
            b_index += 1;
        }

        if sum <= k && ans < a_index + b_index {
            ans = a_index + b_index;
        }
    }
    println!("{}", ans);
}
//  [rust]
use proconio::{input, fastout};
use std::cmp::{max};

#[fastout]
fn main() {
    input! {
        n: usize,
        m: usize,
        k: usize,
        a: [usize; n],
        b: [usize; m],
    }
    let mut temp_cost = 0;
    let mut i = 0;
    while i < a.len() {
        if k < (temp_cost + a[i]) {
            break;
        }
        temp_cost += a[i];
        i += 1;
    }
    let mut res = i;
    let mut j = 0;
    // while j < b.len() && k >= (temp_cost - a[i] + b[j]) {
    while j < b.len() {
        if k >= temp_cost + b[j] {
            temp_cost += b[j];
            j += 1;
            res = max(i + j, res);
        } else {
            if i == 0 {
                break;
            }
            temp_cost -= a[i];
            i -= 1;
        }
    }
    println!("{}", res);
}
//  [rust]
use proconio::{input, fastout};
use std::cmp::{max};

#[fastout]
fn main() {
    input! {
        n: usize,
        m: usize,
        k: usize,
        a: [usize; n],
        b: [usize; m],
    }
    let mut temp_cost = 0;
    let mut i = 0;
    while i < a.len() {
        if k < (temp_cost + a[i]) {
            break;
        }
        temp_cost += a[i];
        i += 1;
    }
    let mut res = i;
    let mut j = 0;
    // while j < b.len() && k >= (temp_cost - a[i] + b[j]) {
    while j < b.len() {
        if k >= temp_cost + b[j] {
            temp_cost += b[j];
            j += 1;
            res = max(i + j, res);
        } else {
            if i == 0 {
                break;
            }
            temp_cost -= a[i];
            i -= 1;
            temp_cost += b[j];
            j += 1;
            res = max(i + j, res);
        }
    }
    println!("{}", res);
}
//  [swift]
import Foundation

func readInts() -> [Int] {
    readLine()!.split(separator: " ").map { Int($0)! }
}

let nmk = readInts()
let (_, _, remaining) = (nmk[0], nmk[1], nmk[2])
let bookA = readInts()
let bookB = readInts()
//
var countCanReadBookB = bookB.count
var readBookTime = bookB.reduce(0) { $0 + $1 }
var varRem = remaining
var ans = 0

for countReadedBookA in 0...bookA.count {
    // Aから0冊読んだ場合から検証するため
    readBookTime += countReadedBookA > 0 ? bookA[countReadedBookA - 1]: 0
    
    
    while countCanReadBookB > 0 && readBookTime > remaining {
        countCanReadBookB -= 1
        readBookTime -= bookB[countCanReadBookB]
    }
    
    if readBookTime > remaining {
        break
    }
    ans = max(ans, countReadedBookA + countCanReadBookB)
}
print(ans)
//  [swift]
// 累積和 + 二分探索
// key以下を満たす最大のインデックスを返す二分探索
func binarySearch(_ key: Int) -> Int{
    var (l, r): (Int, Int) = (0, NMK[1]+1)

    while r-l > 1 {
        let i: Int = (l + r) / 2

        if isOK(idx: i, key: key) { l = i }
        else { r = i }
    }
    return l
}
// key以下かどうか
func isOK(idx: Int, key: Int) -> Bool {
    if csumB[idx] <= key { return true }
    else { return false }
}

let NMK: [Int] = readLine()!.split(separator: " ").map { Int($0)! }
let As: [Int] = readLine()!.split(separator: " ").map { Int($0)! }
let Bs: [Int] = readLine()!.split(separator: " ").map { Int($0)! }

var sum: Int = 0
let csumA: [Int] = [0] + As.map { sum += $0; return sum }
sum = 0
let csumB: [Int] = [0] + Bs.map { sum += $0; return sum }
var (a, b, res): (Int, Int, Int) = (0, 0, 0)

for a in 0...NMK[0] {
    if csumA[a] > NMK[2] { break }
    b = binarySearch(NMK[2]-csumA[a])
    res = max(res, a + b)
}
print(res)  // (๑•ૅㅁ•๑)
//  [swift]
let NMK = readLine()!.split(separator: " ").compactMap { Int($0) }
let k = NMK[2]
let AN = readLine()!.split(separator: " ").compactMap { Int($0) }
let BM = readLine()!.split(separator: " ").compactMap { Int($0) }

let sumAN: [Int] = AN.reduce([0]) { $0 + [($0.last ?? 0) + $1] }
let sumBM = BM.reduce([0]) { $0 + [($0.last ?? 0) + $1] }

var bIndex = sumBM.count - 1

// Caluculate maximized count on each sumA
let maxCountList = sumAN.enumerated().map { sumA -> Int in
    while sumA.element + sumBM[bIndex] > k {
        if bIndex == 0 {
            return 0
        } else {
            bIndex -= 1
        }
    }
    return sumA.offset + bIndex
}
print(maxCountList.max() ?? 0)
//  [swift]
let NMK = readLine()!.split(separator: " ").compactMap { Int($0) }
let k = NMK[2]
let AN = readLine()!.split(separator: " ").compactMap { Int($0) }
let BM = readLine()!.split(separator: " ").compactMap { Int($0) }

let sumAN = AN.reduce([Int]()) { $0 + [($0.last ?? 0) + $1] }
let sumBM = BM.reduce([Int]()) { $0 + [($0.last ?? 0) + $1] }

var bIndex = sumBM.count - 1

// Caluculate maximized count on each sumA
let maxCountList = sumAN.enumerated().reversed().map { sumA -> Int in
    while sumA.element + sumBM[bIndex] > k {
        if bIndex == 0 {
            return 0
        } else {
            bIndex -= 1
        }
    }
    return sumA.offset + bIndex + 2
}
print(maxCountList.max() ?? 0)
//  [swift]
func readThreeInts(separator: String.Element = " ") -> (a: Int, b: Int, c: Int) {
    let ints = readLine()!.split(separator: separator).map { Int($0)! }
    return (a: ints[0], b: ints[1], c: ints[2])
}

func readInts(separator: String.Element = " ") -> [Int] {
    return readLine()!.split(separator: separator).map { Int($0)! }
}

func mainC() {
    let (N, M, K) = readThreeInts()
    let A = readInts()
    let B = readInts()

    var spentTime = 0
    var count = 0
    var aIndex = 0
    var bIndex = 0

    while spentTime < K {
        if aIndex == N, bIndex == M { break }
        let a = aIndex >= N ? Int.max : A[aIndex]
        let b = bIndex >= M ? Int.max : B[bIndex]

        if a < b {
            if spentTime + a <= K {
                spentTime += a
                aIndex += 1
            } else {
                break
            }
        } else {
            if spentTime + b <= K {
                spentTime += b
                bIndex += 1
            } else {
                break
            }
        }

        count += 1
    }

    print(count)
}

mainC()
//  [typescript]
import * as fs from 'fs';

const input = fs.readFileSync('/dev/stdin', 'utf8');

_c(input);

function _c(input: string) {
  const [_nmk, _A, _B] = input.split('\n');
  let k = parseInt(_nmk.split(' ')[2]);
  const A = _A.split(' ').map((s) => parseInt(s));
  const B = _B.split(' ').map((s) => parseInt(s));

  const a = calcSummaries(A, k);
  const b = calcSummaries(B, k);

  let count = 0;
  let maxJ = b.length - 1;

  for (let i = 0; i < a.length; i++) {
    for (let j = maxJ; j >= 0; j--) {
      if (a[i] + b[j] <= k) {
        count = Math.max(i + j, count);
        maxJ = j;
        break;
      }
    }
  }

  console.log(count);
}

/**
 * 机から i 冊 読んだときにかかる時間を a[i] に格納
 */
function calcSummaries(times: number[], limit: number) {
  const sums = [0];
  for (let i = 0; i < times.length; i++) {
    const sum = sums[i] + times[i];
    if (sum <= limit) {
      sums[i + 1] = sum;
    } else {
      break;
    }
  }
  return sums;
}
//  [typescript]
import { readFileSync } from 'fs'

const toTimeList = (books: number[]) =>
  books.reduce((acc, v, i) => (acc.push(acc[i] + v), acc), [0])

function main(input: string) {
  const [[N, M, K], deskA, deskB] = input.split('\n').map(v => v.split(' ').map(Number))

  const timeListA = toTimeList(deskA)
  const timeListB = toTimeList(deskB)

  let result = 0
  let b = M
  for (const [a, time] of timeListA.entries()) {
    if (time > K) break

    while (timeListB[b] + time > K) {
      --b
    }

    result = Math.max(result, a + b)
  }

  console.log(result)
}

main(readFileSync('/dev/stdin', 'utf8').trim())
//  [typescript]
import { readFileSync } from 'fs'

const toTimeList = (books: number[]) =>
  books.reduce((acc, v, i) => [...acc, acc[i] + v], [0])

function main(input: string) {
  const [[N, M, K], deskA, deskB] = input.split('\n').map(v => v.split(' ').map(Number))

  const timeListA = toTimeList(deskA)
  const timeListB = toTimeList(deskB)

  let result = 0
  let b = M
  for (const [a, time] of timeListA.entries()) {
    if (time > K) break

    while (timeListB[b] + time > K) {
      --b
    }

    result = Math.max(result, a + b)
  }

  console.log(result)
}

main(readFileSync('/dev/stdin', 'utf8').trim())
//  [typescript]
import * as fs from 'fs';

const input = fs.readFileSync('input.txt', 'utf8');
// const input = fs.readFileSync('/dev/stdin', 'utf8');

_c(input);

function _c(input: string) {
  const [_nmk, _A, _B] = input.split('\n');
  let k = parseInt(_nmk.split(' ')[2]);
  const A = _A.split(' ').map((s) => parseInt(s));
  const B = _B.split(' ').map((s) => parseInt(s));

  const a = calcSummaries(A, k);
  const b = calcSummaries(B, k);

  let count = 0;
  let maxJ = b.length - 1;

  for (let i = 0; i < a.length; i++) {
    for (let j = maxJ; j >= 0; j--) {
      if (a[i] + b[j] <= k) {
        count = Math.max(i + j, count);
        maxJ = j;
        break;
      }
    }
  }

  console.log(count);
}

/**
 * 机から i 冊 読んだときにかかる時間を a[i] に格納
 */
function calcSummaries(times: number[], limit: number) {
  const sums = [0];
  for (let i = 0; i < times.length; i++) {
    const sum = sums[i] + times[i];
    if (sum <= limit) {
      sums[i + 1] = sum;
    } else {
      break;
    }
  }
  return sums;
}
//  [python]
a,b,c,d = map(int,input().split())
def gcd(a, b):
	while b:
		a, b = b, a % b
	return a
e = gcd(c,d)
f = c * d // e

b_c = b // c
s_c = (a-1) // c
C = b_c - s_c

b_d = b // d
s_d = (a-1) // d
D = b_d - s_d

b_cd = b // f
s_cd = (a-1) // f
CD = b_cd - s_cd

ans = b - a + 1 - (C + D - CD)
print(ans)
//  [python]
def gcd(x, y):
    while y > 0:
        x, y = y, x%y
    return x

A,B,C,D = map(int, input().split())
B_C = B // C
B_D = B // D
g = gcd(C,D)
l = C * D // g
duplicate_B = B // l
answer_B = B - B_C - B_D + duplicate_B

A_C = (A - 1) // C
A_D = (A - 1) // D
duplicate_A = (A - 1) // l
answer_A = (A - 1) - A_C - A_D + duplicate_A
print(int(answer_B - answer_A))
//  [python]
def gcd(a: int, b: int) -> int:
    return gcd(b, a % b) if b > 0 else a


A, B, C, D = map(int, input().split())


def calc(n: int, div: int) -> int:
    assert div > 0
    return n // div


def calc2(l: int, r: int, div: int) -> int:
    assert r >= l
    assert div > 0
    return calc(r, div) - calc(l - 1, div)


lcm = (C * D) // gcd(C, D)

k = calc2(A, B, C) + calc2(A, B, D) - calc2(A, B, lcm)
print(B - A + 1 - k)
//  [python]
import math

a,b,c,d = map(int,input().split())

s1=b//c - (a-1)//c
s2=b//d - (a-1)//d
s12=b//(c*d/math.gcd(c,d)) - (a-1)//(c*d/math.gcd(c,d))
s12=int(s12)
#print(s1,s2,s12)
print(b-a+1-(s1+s2-s12))
//  [python]
import math

a,b,c,d = map(int,input().split())

s1=b//c - (a-1)//c
s2=b//d - (a-1)//d
s12=b//(c*d/math.gcd(c,d)) - (a-1)//(c*d/math.gcd(c,d))
s12=int(s12)
print(s1,s2,s12)
print(b-a+1-(s1+s2-s12))
//  [python]
import math

a,b,c,d = map(int,input().split())
lcm=c*d/math.gcd(c,d)

s1=b//c - (a-1)//c
s2=b//d - (a-1)//d
s12=b//lcm - (a-1)//lcm

print(int(b-a+1-(s1+s2-s12)))
//  [java]
import java.util.*;
import java.io.*;
import static java.lang.System.*;

class FastScanner {
  private final InputStream in = System.in;
  private final byte[] buffer = new byte[1024];
  private int ptr = 0;
  private int buflen = 0;
  private boolean hasNextByte() {
      if (ptr < buflen) {
          return true;
      }else{
          ptr = 0;
          try {
              buflen = in.read(buffer);
          } catch (IOException e) {
              e.printStackTrace();
          }
          if (buflen <= 0) {
              return false;
          }
      }
      return true;
  }
  private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1;}
  private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
  public boolean hasNext() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++; return hasNextByte();}
  public String next() {
      if (!hasNext()) throw new NoSuchElementException();
      StringBuilder sb = new StringBuilder();
      int b = readByte();
      while(isPrintableChar(b)) {
          sb.appendCodePoint(b);
          b = readByte();
      }
      return sb.toString();
  }
  public long nextLong() {
      if (!hasNext()) throw new NoSuchElementException();
      long n = 0;
      boolean minus = false;
      int b = readByte();
      if (b == '-') {
          minus = true;
          b = readByte();
      }
      if (b < '0' || '9' < b) {
          throw new NumberFormatException();
      }
      while(true){
          if ('0' <= b && b <= '9') {
              n *= 10;
              n += b - '0';
          }else if(b == -1 || !isPrintableChar(b)){
              return minus ? -n : n;
          }else{
              throw new NumberFormatException();
          }
          b = readByte();
      }
  }
  public int nextInt() {
      long nl = nextLong();
      if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE) throw new NumberFormatException();
      return (int) nl;
  }
  public double nextDouble() { return Double.parseDouble(next());}
}

class Main {
  public static final int MOD = 1000000007;
  public static final int INF = 1000000000;
  public static void main(String[] args) {
    FastScanner sc = new FastScanner();
    long A = sc.nextLong();
    long B = sc.nextLong();
    int C = sc.nextInt();
    int D = sc.nextInt();
    long lcm = (long)C * D / gcd(C, D);
    long countB = B - (B / C + B / D - B / lcm);
    long countA = (A-1) - ( (A-1) / C + (A-1) / D - (A-1) / lcm);
    long ans = countB - countA;
    out.println(ans);
  }

  public static int gcd(int a, int b){
    if(b == 0) return a;
    return gcd(b, a%b);
  }
}
//  [java]
import java.util.*;

public class Main {
    public static void main(String[] args){
        // Your code here!
      Scanner sc = new Scanner(System.in);
      long a = sc.nextLong();
      long b = sc.nextLong();
      long c = sc.nextLong();
      long d = sc.nextLong();
        
        long count = 0L;
        
        for( long i = a ; i <= b ; i++){
            
            if(i % c == 0){
                continue;
            }
            if(i % d == 0){
                continue;
            }
            count++;
        }
      
      System.out.println(count);
      
    }
}
//  [java]
import java.util.*;
 
public class Main{
  public static void main(String[] args){
    Scanner sc = new Scanner(System.in);
    long low = sc.nextLong();
    long high = sc.nextLong();
    long a = sc.nextLong();
    long b = sc.nextLong();
    int count = 0;
    for(long i = low;i <= high;i++){
      if((i % a != 0) && (i % b != 0)){
        count++;
      }
    }
  }
}
//  [java]
import java.util.*;
 
public class Main{
  public static void main(String[] args){
    Scanner sc = new Scanner(System.in);
    long low = sc.nextLong();
    long high = sc.nextLong();
    long a = sc.nextLong();
    long b = sc.nextLong();
    int count = 0;
    for(long i = low;i <= high;i++){
      if((i % a != 0) && (i % b != 0)){
        count++;
      }
    }
//  [cpp]
#include<cstdio>
long long int gcd(long long int x, long long int y){
	if(x<y){
		long long int z=x;
		x=y;
		y=z;
	}
	if(x%y==0)return y;
	else return gcd(y,x%y);
}
int main(){
	long long int a,b,c,d;
	scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
	long long int ans=0;
	ans+=( (b/c)-((a-1)/c) );
	ans+=( (b/d)-((a-1)/d) );
	long long int lcm=c*d/gcd(c, d);
	ans-=( (b/lcm)-((a-1)/lcm) );
	printf("%lld\n",b-a+1-ans);
	return 0;
}
//  [cpp]
#define _CRT_SECURE_NO_WARNINGS

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>

using namespace std;

long long int gcd(long long int a, long long int b)
{
	return b != 0 ? gcd(b, a%b) : a;
}

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

int main()
{
	FILE *fin = NULL, *fout = NULL;
	//fin = freopen("input.txt", "r", stdin);
	//fout = freopen("output.txt", "w", stdout);
	

	long long int A, B, C, D; scanf("%lld%lld%lld%lld", &A, &B, &C, &D);
	long long int CD = lcm(C, D);

	long long int div = (B / C + B / D - B / CD) - ((A - 1) / C + (A - 1) / D - (A - 1) / CD);
	printf("%lld", B - A + 1 - div);

	//finalize
	if (NULL != fin) fclose(fin);
	if (NULL != fout) fclose(fout);

	return 0;
}
//  [cpp]
#include <bits/stdc++.h>
using namespace std;
int gcd(long int a, long int b){
    long int min_ = min(a, b);
    long int max_ = max(a, b);
    if (min_ == 0)
    {
        return max_;
    }
    else
    {
        return gcd(min_, max_ % min_);
    }
}

int main(void){
    long int A, B, C, D;
    cin >> A >> B >> C >> D;
    long int lcm;
    lcm = C / gcd(C, D) * D;
    long int c, d, cd;
    c = B / C - (A-1) / C;
    d = B / D - (A-1) / D;
    cd = B / lcm - (A-1) / lcm;
    cout << B - A - c - d + cd + 1 << endl;
    return 0;
}
//  [cpp]
#include <bits/stdc++.h>
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define ALL(c) (c).begin(),(c).end()
#define RALL(c) (c).rbegin(),(c).rend()
using namespace std;
using ll = long long;
using P = pair<int,int>;
#define chmax(x,y) x = max(x,y)
#define chmin(x,y) x = min(x,y)

const ll INF = 1e18 + 10;

ll A, B, C, D;

int main() {
    cin >> A >> B >> C >> D;
    ll G = __gcd(C,D);
    A--;
    ll divC1 = A - A/C;
    ll divC2 = B - B/C;
    ll divD1 = A - A/D;
    ll divD2 = B - B/D;
    ll divCD1 = A - A/C/D*G;
    ll divCD2 = B - B/C/D*G;

    ll div1 = divC1 + divD1 - divCD1;
    ll div2 = divC2 + divD2 - divCD2;
    cout << div2 - div1 << endl;
}
//  [cpp]
#include <bits/stdc++.h>
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define ALL(c) (c).begin(),(c).end()
#define RALL(c) (c).rbegin(),(c).rend()
using namespace std;
using ll = long long;
using P = pair<int,int>;
#define chmax(x,y) x = max(x,y)
#define chmin(x,y) x = min(x,y)

const ll INF = 1e18 + 10;

ll A, B, C, D;

int main() {
    cin >> A >> B >> C >> D;
    ll G = __gcd(C,D);
    A--;
    ll divC1 = A - A/C;
    ll divC2 = B - B/C;
    ll divD1 = A - A/D;
    ll divD2 = B - B/D;
    ll divCD1 = A - G*A/C/D;
    ll divCD2 = B - G*B/C/D;

    ll div1 = divC1 + divD1 - divCD1;
    ll div2 = divC2 + divD2 - divCD2;
    cout << div2 - div1 << endl;
}
//  [cpp]
#include <bits/stdc++.h>
#define f(i,j,k) for(int i=j;i<k;i++)
using namespace std;
int main(){
    long long a,b,c,d;
    cin>>a>>b>>c>>d;
    long long e=c*d;
    long long ac=(a-1)/c,ad=(a-1)/d,ae=(a-1)/e;
    long long bc=b/c,bd=b/d,be=b/e;
    long long ans=(b-a+1)-(bc-ac)-(bd-ad)+(be-ae);
    cout<<ans<<endl;
    return 0;
}
//  [c]
#include <stdio.h>
#include <math.h>

int gcd(int x, int y){
    int r;
    while((r = x % y) != 0){
        x = y;
        y = r;
    }
    return y;
}

long long lcm(int x, int y){
    return ((long long)x * y / gcd(x, y));
}
long long a,b,lcmCD;
int c,d;

long long numCount(long long x){
	return x-((x/c)+(x/d)-(x/lcmCD));
}
int main(){
	scanf("%lld%lld%d%d", &a,&b,&c,&d);
	lcmCD=lcm(c,d);
	printf("%lld\n",numCount(b)-numCount(a-1));
	return 0;
}
//  [c]
#include <stdio.h>

long get_count(long A, long B, long target) {
    if (B < target)
        return 0;
    long mod_a = A % target;
    long mod_b = B % target;
    long initial = (mod_a == 0) ? A : A + (target - mod_a); // 最初に割り切れる値
    long last = B - mod_b;
    long initial_count = initial / target;
    long last_count = last / target;
    return last_count - initial_count + 1;
}

long gcd(long m, long n) {
    long tmp;
    while (m % n != 0) {
        tmp = n;
        n = m % n;
        m = tmp;
    }

    return n;
}

long lcm(long m, long n) {
    return m * n / gcd(m, n);
}

int main () {
    long A;
    long B;
    long C;
    long D;

    scanf("%ld", &A);
    scanf("%ld", &B);
    scanf("%ld", &C);
    scanf("%ld", &D);

    long divided_c = get_count(A, B, C);
    //printf("c: %ld\n", divided_c);
    long divided_d = get_count(A, B, D);
    //printf("d: %ld\n", divided_d);
    long divided_c_d = get_count(A, B, lcm(C, D));
    //printf("lcm: %ld\n", lcm(C, D));
    //printf("c_d: %ld\n", divided_c_d);

    long ans = (B - A + 1) - (divided_c - divided_c_d + divided_d);

    printf("%ld\n", ans);

    return 0;
}
//  [c]
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>

#define lli long long int
lli g(lli a, lli b)
{
	lli tmp;
	lli x = a*b;
	if (a<b)
	{
		tmp = a;
		a = b;
		b = tmp;
	}
	lli r = a%b;
	while (r!=0)
	{
		a = b;
		b = r;
		r = a%b;
	}
	return (x/b);
}

lli f(lli a, lli b, lli c)
{
	if (a == b)
	{
		if (a%c == 0)
			return (1);
		return (0);
	}

	lli small = a + (c - a%c)%c;
	lli big = (b/c)*c;
	if(small == big)
		return (1);
	return(1+((big - small)/c));
}
int main(void)
{
	lli a, b, c, d;
	scanf("%lld %lld %lld %lld",&a, &b, &c, &d);
	lli out = 0;
	lli by_c = f(a,b,c);
	lli by_d = f(a,b,d);
	//printf("debug:c:%lld\n",by_c);
	//printf("debug:d:%lld\n",by_d);

	lli e = g(c,d);
	//printf("debug:gcd:%lld\n",e);
	lli by_e = f(a,b,e);
	//printf("debug:e:%lld\n",by_e);

	out = b - a + 1;
	out = out - by_c - by_d + by_e;
	printf("%lld\n",out);
	return (0);
}
//  [c]
#include<stdio.h>
long long int lcm(long long int a,long long int b){
    long long int max=(a>b)?a:b;
    while(1){
        if(max%a==0 && max%b==0){
            break;
        }
        max++;
    }
    return max;
}
int main(){
	long long int a,b,c,d;
	scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
    long long int p,count=b-a+1;
    count-=(a%c==0)?(b/c-a/c+1):(b/c-a/c);
   // printf("%lld\n",count);
    count-=(a%d==0)?(b/d-a/d+1):(b/d-a/d);
   // printf("%lld\n",count);
    p=lcm(c,d);
    count+=(a%p==0)?(b/p-a/p+1):(b/p-a/p);
    
    
	printf("%lld\n",count);
}
//  [c]
#include<stdio.h>
int main(){
	long long int a,b,c,d;
	scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
	long long int i=0,count=0;
	for(i=a;i<=b;i++){
		if(i%c!=0 && i%d!=0)
		count++;
	}
	printf("%lld\n",count);
}
//  [c]
#include <stdio.h>

int main()
{
	long a,b,c,d;
	int count = 0;

	scanf("%ld %ld %ld %ld", &a,&b,&c,&d);

	for(long i = a; i <= b; i++)
	{
		if(i%c!=0 && i%d!=0) count++;
	}

	printf("%d", count);

	return 0;
}
//  [javascript]
console.log((args=>{
  const [A,B,C,D] = args.trim().split(' ').map(BigInt);
  const gcd = (a,b) => {while(a)[a,b]=[b%a,a]; return b;};
  const A2B = B - A + 1n;
  const divC = B/C - (A-1n)/C;
  const divD = B/D - (A-1n)/D;
  const CD = C*D/gcd(C,D);
  const divCD = B/CD - (A-1n)/CD;

  return `${A2B - divC - divD + divCD}`
})(require('fs').readFileSync('/dev/stdin', 'utf8')));
//  [javascript]
"use strict"
const create = () => {
    const input = require("fs").readFileSync("/dev/stdin", "utf8").trim().split("\n");
    const res = {
        "list": input, "index": 0, "max": input.length,
        "hasNext": function () { return this.index < this.max },
        "next": function () { if (!this.hasNext()) { throw "ArrayIndexOutOfBoundsException"; } else { return this.list[this.index++]; } }
    };
    return res;
}
const o = create();
const next = () => o.next()
const nextInt = () => parseInt(o.next())
const nextStrArray = () => o.next().split(" ")
const nextIntArray = () => o.next().split(" ").map(el => parseInt(el))
const nextCharArray = () => o.next().split("")
const hasNext = () => o.hasNext()
const myout = (...x) => console.log(...x)
const euc = (x, y) => {
    if (x == 0) return y
    if (y == 0) return x
    if (x > y) {
        return euc(x % y, y)
    } else {
        return euc(y % x, x)
    }
}
const Main = () => {
    const [A, B, C, D] = next().split(" ").map(el => BigInt(el))
    //B
    let bc = B / C
    let bd = B / D
    let min = C * D / euc(C, D)
    let bcd = B / min
    let b = B - bc - bd + bcd
    //A
    let ac = (A-1n) / C
    let ad = (A-1n) / D
    let acd = (A-1n) / min
    let a = A-1n - ac - ad + acd

    console.log(Number(b - a))
}
Main()
//  [javascript]
const input = require("fs").readFileSync("/dev/stdin", "utf8").split("\n");

const N = input[0].split(' ').map(item => parseInt(item))[0]
input.shift()
input.pop()

AB = input.map(item => item.split(' ').map(item2 => parseInt(item2)))
const A = AB.map(item => item[0])
const B = AB.map(item => item[1])

// console.log(AB)
AB.sort((a, b) => a[1] - b[1])
// console.log(AB)

count = 0
for (let i = 0; i < N; i++) {
    count += AB[i][0]
    if (count > AB[i][1]) {
        console.log('No')
        return
    }
}
console.log('Yes')
//  [go]
package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
	"strconv"
)

func out(x ...interface{}) {
	fmt.Println(x...)
}

var sc = bufio.NewScanner(os.Stdin)

func getInt() int {
	sc.Scan()
	i, e := strconv.Atoi(sc.Text())
	if e != nil {
		panic(e)
	}
	return i
}

func getString() string {
	sc.Scan()
	return sc.Text()
}

// min, max, asub, absなど基本関数
func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func asub(a, b int) int {
	if a > b {
		return a - b
	}
	return b - a
}

func abs(a int) int {
	if a >= 0 {
		return a
	}
	return -a
}

func lowerBound(a []int, x int) int {
	idx := sort.Search(len(a), func(i int) bool {
		return a[i] >= x
	})
	return idx
}

func upperBound(a []int, x int) int {
	idx := sort.Search(len(a), func(i int) bool {
		return a[i] > x
	})
	return idx
}

// GCD : greatest common divisor (GCD) via Euclidean algorithm
func GCD(a, b int) int {
	for b != 0 {
		t := b
		b = a % b
		a = t
	}
	return a
}

// LCM : find Least Common Multiple (LCM) via GCD
func LCM(a, b int, integers ...int) int {
	result := a / GCD(a, b) * b

	for i := 0; i < len(integers); i++ {
		result = LCM(result, integers[i])
	}

	return result
}
func main() {
	sc.Split(bufio.ScanWords)
	A, B, C, D := getInt(), getInt(), getInt(), getInt()

	n := B - A + 1

	E := LCM(C, D)

	c := B/C - (A-1)/C
	d := B/D - (A-1)/D
	e := B/E - (A-1)/E

	out(n - c - d + e)
}
//  [go]
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func out(x ...interface{}) {
	fmt.Println(x...)
}

var sc = bufio.NewScanner(os.Stdin)

func getInt() int {
	sc.Scan()
	i, e := strconv.Atoi(sc.Text())
	if e != nil {
		panic(e)
	}
	return i
}

func getString() string {
	sc.Scan()
	return sc.Text()
}

// min, max, asub, absなど基本関数
func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func asub(a, b int) int {
	if a > b {
		return a - b
	}
	return b - a
}

func abs(a int) int {
	if a >= 0 {
		return a
	}
	return -a
}

// GCD : greatest common divisor (GCD) via Euclidean algorithm
func GCD(a, b int) int {
	for b != 0 {
		t := b
		b = a % b
		a = t
	}
	return a
}

// LCM : find Least Common Multiple (LCM) via GCD
func LCM(a, b int, integers ...int) int {
	result := a / GCD(a, b) * b

	for i := 0; i < len(integers); i++ {
		result = LCM(result, integers[i])
	}

	return result
}

func main() {
	sc.Split(bufio.ScanWords)

	A, B, C, D := getInt(), getInt(), getInt(), getInt()
	A--

	lcm := LCM(C, D)
	t := B / lcm
	f := A / lcm
	tc := B / C
	fc := A / C
	td := B / D
	fd := A / D

	ans := B - A
	ans -= tc - fc
	ans -= td - fd
	ans += t - f
	out(ans)
}
//  [go]
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"sort"
	"strconv"
)

func main() {
	a := readi64()
	b := readi64()
	c := readi64()
	d := readi64()

	divC := (b / c) - ((a - 1) / c)
	divD := (b / d) - ((a - 1) / d)
	cd := lcm64(c, d)
	divCD := (b / cd) - ((a - 1) / cd)

	ans := (b - (a - 1)) - (divC + divD - divCD)

	fmt.Println(ans)
}

func lcm64(a, b int64) int64 {
	return (a * b) / gcd64(a, b)
}

func gcd64(a, b int64) int64 {
	if b == 0 {
		return a
	}
	return gcd64(b, a%b)
}

/*-------------------utilities-------------------*/

func abs(x int) int {
	if x < 0 {
		return -x
	}
	return x
}

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}

func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}

func chmin(x *int, y int) bool {
	if *x > y {
		*x = y
		return true
	}
	return false
}

func chmax(x *int, y int) bool {
	if *x < y {
		*x = y
		return true
	}
	return false
}

func gcd(a, b int) int {
	if b == 0 {
		return a
	}
	return gcd(b, a%b)
}

func lcm(a, b int) int {
	return (a * b) / gcd(a, b)
}

func comb(n, k int) int {
	if n < k {
		return 0
	}
	if n < 0 || k < 0 {
		return 0
	}
	return fac[n] * (finv[k] * finv[n-k] % MOD) % MOD
}

func permutations(arr []int) [][]int {
	var helper func([]int, int)
	res := [][]int{}

	helper = func(arr []int, n int) {
		if n == 1 {
			tmp := make([]int, len(arr))
			copy(tmp, arr)
			res = append(res, tmp)
		} else {
			for i := 0; i < n; i++ {
				helper(arr, n-1)
				if n%2 == 1 {
					tmp := arr[i]
					arr[i] = arr[n-1]
					arr[n-1] = tmp
				} else {
					tmp := arr[0]
					arr[0] = arr[n-1]
					arr[n-1] = tmp
				}
			}
		}
	}
	helper(arr, len(arr))
	return res
}

func isPrime(n int) bool {
	if n == 1 {
		return false
	}
	for i := 2; i*i <= n; i++ {
		if n%i == 0 {
			return false
		}
	}
	return true
}

func divisor(n int) (res []int) {
	for i := 1; i*i <= n; i++ {
		if n%i == 0 {
			res = append(res, i)
			if i*i != n {
				res = append(res, n/i)
			}
		}
	}
	sort.Ints(res)
	return
}

/*-------------------init-------------------*/

const (
	INF = 1000000000000000000
	MOD = 1e9 + 7

	COMB_MAX = 510000
)

var (
	readString func() string
)

var (
	fac  = [COMB_MAX]int{}
	finv = [COMB_MAX]int{}
	inv  = [COMB_MAX]int{}
)

func init() {
	readString = newReadString(os.Stdin)
}

func combInit() {
	fac[0] = 1
	fac[1] = 1
	finv[0] = 1
	finv[1] = 1
	inv[1] = 1
	for i := 2; i < COMB_MAX; i++ {
		fac[i] = fac[i-1] * i % MOD
		inv[i] = MOD - inv[MOD%i]*(MOD/i)%MOD
		finv[i] = finv[i-1] * inv[i] % MOD
	}
}

/*-------------------inputs-------------------*/

func readi() int {
	return int(readi64())
}

func readi64() int64 {
	i, err := strconv.ParseInt(readString(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

func readf() float64 {
	f, err := strconv.ParseFloat(readString(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

func newReadString(ior io.Reader) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+11))
	r.Split(bufio.ScanWords)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}
//  [go]
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)

func init() {
	sc.Split(bufio.ScanWords)
	sc.Buffer(make([]byte, 1024*1024), bufio.MaxScanTokenSize)
}

func nextInt() int {
	sc.Scan()
	i, e := strconv.Atoi(sc.Text())
	if e != nil {
		panic(e)
	}
	return i
}

func main() {
	A := nextInt()
	B := nextInt()
	C := nextInt()
	D := nextInt()
	E := lcm(C, D)
	ANS := B - A - (B / C) - (B / D) + ((A - 1) / C) + ((A - 1) / D) + (B / E) + 1
	fmt.Println(ANS)
}

func gcd(a, b int) int {
	if b > a {
		a, b = b, a
	}
	for b != 0 {
		t := b
		b = a % b
		a = t
	}
	return a
}

func lcm(a, b int) int {
	return a * b / gcd(a, b)
}
//  [go]
package main

import "fmt"

func main() {
	var a, b, c, d int
	fmt.Scanf("%d %d %d %d", &a, &b, &c, &d)

	// 一番最初に割り切れるやつ

	cleft := a + a%c
	dleft := a + a%d

	cdleft := a + a%(c*d)

	ccount := int((b - cleft) / c)
	dcount := int((b - dleft) / d)
	cdcount := int((b - cdleft) / (c * d))

	ans := (b - a) - (ccount + dcount - cdcount)

	fmt.Println(ans)
}
//  [go]
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

var sc = bufio.NewReaderSize(os.Stdin, 1024*1024*1)

func main() {
	list := getStdinIntArr64()
	var A int64 = list[0]
	var B int64 = list[1]
	var C int64 = list[2]
	var D int64 = list[3]

	var cnt int64 = B - A + 1

	if A%C == 0 {
		cnt -= (B-A)/C + 1
	} else {
		cnt -= (B - A) / C
	}

	if A%D == 0 {
		cnt -= (B-A)/D + 1
	} else {
		cnt -= (B - A) / D
	}

	l := lcm(C, D)
	if A%l == 0 {
		cnt += (B-A)/l + 1
	} else {
		cnt += (B - A) / l
	}

	fmt.Printf("%d\n", cnt)
}

func gcd(a, b int64) int64 {
	if b == 0 {
		return a
	}
	return gcd(b, a%b)
}
func lcm(a, b int64) int64 {
	return a * b / gcd(a, b)
}

func getStdin() string {
	return readLine()
}
func getStdinInt() int {
	str := getStdin()
	rtn, _ := strconv.Atoi(str)
	return rtn
}
func getStdinInt64() int64 {
	str := getStdin()
	rtn, _ := strconv.ParseInt(str, 10, 64)
	return rtn
}
func getStdinIntArr() []int {
	str := getStdin()
	list := strings.Split(str, " ")
	rtn := make([]int, len(list))
	for idx, val := range list {
		rtn[idx], _ = strconv.Atoi(val)
	}
	return rtn
}

func getStdinArr() []string {
	str := getStdin()
	list := strings.Split(str, " ")
	return list
}

func getStdinIntArr64() []int64 {
	str := getStdin()
	list := strings.Split(str, " ")
	rtn := make([]int64, len(list))
	for idx, val := range list {
		rtn[idx], _ = strconv.ParseInt(val, 10, 64)
	}
	return rtn
}

func readLine() string {
	buf := make([]byte, 0, 0)
	for {
		l, p, e := sc.ReadLine()
		if e != nil {
			panic(e)
		}
		buf = append(buf, l...)
		if !p {
			break
		}
	}
	return string(buf)
}
//  [ruby]
A,B,C,D = gets.split.map(&:to_i)
e = C.lcm(D)
a = A - 1
x = a/C + a/D - a/e
y = B/C + B/D - B/e
z = y - x
puts (B-A+1) - z
//  [ruby]
#input of int(split by space)
def get_i()
  return gets.chomp.split(" ").map(&:to_i)
end
#input of float(split by space)
def get_f()
  return gets.chomp.split(" ").map(&:to_f)
end
#input of string(split by space)
def get()
  return gets.chomp.split(" ")
end
#input of string(split per one character)
def get_nsp()
  return gets.chomp.split("")
end
#yes or no decision
def yn_judge(bool,y="Yes",n="No")
  return bool ? y : n 
end
#create of array
def array(size1,init=nil,size2=-1)
  if size2==-1
    return Array.new(size1){init}
  else
    return Array.new(size2){Array.new(size1){init}}
  end
end

def max(a,b)
    return a>b ? a : b
end

def min(a,b)
    return a>b ? b : a
end

INF=Float::INFINITY

def add(x,y)
    return (x%y).zero? ? 1 : 0
end
A,B,C,D=get_i
puts (B-A+1)-((B/C-A/C+add(A,C))+(B/D-A/D+add(A,D))-(B/C.lcm(D)-A/C.lcm(D)+add(A,C.lcm(D))))
//  [ruby]
A,B,C,D=$<.read.split.map(&:to_i)

a = A-1
x = B - B/C - B/D + B/C.lcm(D)
y = a - a/C - a/D + a/C.lcm(D)

puts x-y
//  [ruby]
a,b,c,d = gets.chomp.split(' ').map(&:to_i)
c_a = (a/c.to_f).ceil
d_a = (a/d.to_f).ceil
c_b = b/c
d_b = b/d
lcm = c.lcm(d)
lcm_a = (a/lcm.to_f).ceil
lcm_b = b/lcm
# puts "#{a}と#{b}の間の#{c}の倍数の個数は#{(b/c - (a/c.to_f).ceil ) + 1} "
# puts "#{a}と#{b}の間の#{d}の倍数の個数は#{(b/d - (a/d.to_f).ceil) + 1}"
# puts "#{a}と#{b}の間の#{c}と#{d}の公倍数の個数は#{lcm_b - lcm_a + 1}"
puts b - a + 1 - (c_b - c_a + 1) - (d_b - d_a + 1) + (lcm_b - lcm_a + 1)
//  [ruby]
a,b,c,d = gets.chomp.split(' ').map(&:to_i)
c_a = (a/c.to_f).ceil
d_a = (a/d.to_f).ceil
c_b = b/c
d_b = b/d
lcm = c.lcm(d)
lcm_a = (a/lcm).ceil
lcm_b = b/lcm

puts b - a + 1 - (c_b - c_a+1) - (d_b - d_a+1) + (lcm_b - lcm_a)
//  [ruby]
a,b,c,d = gets.strip.split.map(&:to_i)
s = b.to_f/c-((a-1).to_f/c)
t = b.to_f/d-((a-1).to_f/d)
e = c.lcm(d)
u = b.to_f/e-((a-1).to_f/e)
puts b-a+1-(s+t-u)
//  [rust]
#[allow(unused_imports)]
use std::collections::HashSet;

fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}

#[allow(dead_code)]
fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim()
        .split_whitespace()
        .map(|e| e.parse().ok().unwrap())
        .collect()
}

fn main() {
    let abcd = read_vec::<u64>();
    let a = abcd[0];
    let b = abcd[1];
    let c = abcd[2];
    let d = abcd[3];
    


    let answer = solve(a, b, c, d);
    println!("{}", answer);
}

fn solve(a: u64, b:u64, c:u64, d:u64) -> u64 {
    let total = b - a + 1;
    let cc = b / c  - (a - 1) / c;
    let dd = b / d - (a - 1) / d;
    
    let l = lcm(c, d);
    let ll = b / l - (a - 1) / l;

    //println!("{}, {}, {}, {}", total, cc, dd, ll);
    
    return total - cc - dd + ll;
}

fn lcm(a: u64, b: u64) -> u64 {
    return a * b / gcd(a, b)
}

fn gcd(a: u64, b: u64) -> u64 {
    let mut m : u64 = a;
    let mut n : u64 = b;
    if m < n {
        m = b;
        n = a;
    }

    loop {
        let r = m % n;
        if r == 0 {
            return n;
        }
        m = n;
        n = r;    
    }
}
//  [rust]
fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>()
        .split_whitespace()
        .map(|s| s.parse().ok().unwrap())
        .collect()
}

fn gcd(a: usize, b: usize) -> usize {
    if a % b == 0 {
        b
    } else {
        gcd(b, a % b)
    }
}
fn lcm(a: usize, b:usize) -> usize {
    a / gcd(a, b) * b
}



fn main() {
    let input = read_vec::<usize>();
    let (a,b,c,d) = (input[0], input[1], input[2], input[3]);

    let mut count = b - a + 1;

    let c_div = b / c - (a-1) / c;
    let d_div = b / d - (a-1) / d;
    let lcm = lcm(c, d);
    let lcm_div = b / lcm - (a-1) / lcm;

    count -= c_div;
    count -= d_div;
    count += lcm_div;

    println!("{}", count);
}
//  [rust]
use std::io::*;
fn gcd(a: u64, b: u64) -> u64 {
    if b == 0 {
        return a;
    }
    gcd(b, a % b)
}
fn lcm(a: u64, b: u64) -> u64 {
    a / gcd(a, b) * b
}
fn main() {
    let mut s: String = String::new();
    std::io::stdin().read_to_string(&mut s).ok();
    let mut itr = s.trim().split_whitespace();
    let a: u64 = itr.next().unwrap().parse::<u64>().unwrap() - 1;
    let b: u64 = itr.next().unwrap().parse().unwrap();
    let c: u64 = itr.next().unwrap().parse().unwrap();
    let d: u64 = itr.next().unwrap().parse().unwrap();

    let l = lcm(c, d);
    let x = b + b / l - b / c - b / d;
    let y = a + a / l - a / c - a / d;

    println!("{}", x - y);
}
//  [rust]

fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().split_whitespace().map(|e| e.parse().ok().unwrap()).collect()
}

fn read_vec2<T: std::str::FromStr>(n: u32) -> Vec<Vec<T>> {
    let mut v2 = Vec::new();
    for _ in 0..n {
        let mut s = String::new();
        std::io::stdin().read_line(&mut s).ok();
        let v = s.trim().split_whitespace()
            .map(|e| e.parse().ok().unwrap()).collect();
        v2.push(v);
    }
    v2
}

fn gcd(a:u128, b:u128) -> u128 {

    let mut a = a;
    let mut b = b;
    let mut tmp = 0;
    if a < b {
        tmp = a;
        a = b;
        b = tmp;
    }

    let mut r = a % b;
    while r !=0 {
        a = b;
        b = r;
        r = a % b;
    }

    b
}

fn canti() {

    let data: Vec<u128> = read_vec();

    let lcm = data[2]*data[3]/gcd(data[2],data[3]);
    let a = data[1] - ( data[1]/data[2] + data[1]/data[3] - data[1]/lcm) ;
    let b = data[0]-1 - ( (data[0]-1)/data[2] + (data[0]-1)/data[3] - data[0]/lcm);


    println!("{}", a-b);
}

fn main() {
    canti();
}
//  [rust]
fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().split_whitespace().map(|e| e.parse().ok().unwrap()).collect()
}

fn read_vec2<T: std::str::FromStr>(n: u32) -> Vec<Vec<T>> {
    let mut v2 = Vec::new();
    for _ in 0..n {
        let mut s = String::new();
        std::io::stdin().read_line(&mut s).ok();
        let v = s.trim().split_whitespace()
            .map(|e| e.parse().ok().unwrap()).collect();
        v2.push(v);
    }
    v2
}

fn gcd(a:u128, b:u128) -> u128 {

    let mut a = a;
    let mut b = b;
    let mut tmp = 0;
    if a < b {
        tmp = a;
        a = b;
        b = tmp;
    }

    let mut r = a % b;
    while r !=0 {
        a = b;
        b = r;
        r = a % b;
    }

    b
}

fn canti() {

    let data: Vec<u128> = read_vec();

    let lcm = data[2]*data[3]/gcd(data[2],data[3]);
    let a = data[1] - ( data[1]/data[2] + data[1]/data[3] - data[1]/lcm) ;
    let b = data[0]-1 - ( (data[0]-1)/data[2] + (data[0]-1)/data[3] - data[0]/lcm);


    println!("{}", a-b);
}

fn main() {
    canti();
}
//  [rust]
fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().split_whitespace().map(|e| e.parse().ok().unwrap()).collect()
}

fn read_vec2<T: std::str::FromStr>(n: u32) -> Vec<Vec<T>> {
    let mut v2 = Vec::new();
    for _ in 0..n {
        let mut s = String::new();
        std::io::stdin().read_line(&mut s).ok();
        let v = s.trim().split_whitespace()
            .map(|e| e.parse().ok().unwrap()).collect();
        v2.push(v);
    }
    v2
}

fn gcd(a:usize, b:usize) -> usize {

    let mut a = a;
    let mut b = b;
    let mut tmp = 0;
    if a < b {
        tmp = a;
        a = b;
        b = tmp;
    }

    let mut r = a % b;
    while r !=0 {
        a = b;
        b = r;
        r = a % b;
    }

    b
}

fn canti() {

    let data: Vec<usize> = read_vec();

    let lcm = data[2]*data[3]/gcd(data[2],data[3]);
    let a = data[1] - ( data[1]/data[2] + data[1]/data[3] - data[1]/lcm) ;
    let b = data[0]-1 - ( (data[0]-1)/data[2] + (data[0]-1)/data[3] - data[0]/lcm);
    

    println!("{}", a-b);
}

fn main() {
    canti();
}
//  [swift]
let i=readLine()!.characters.split(" ").map{Int(String($0))!},C=i[2],D=i[3];func f(x:Int)->Int{return i[1]/x-(i[0]-1)/x};func g(x:Int,_ y:Int)->Int{return y>0 ?g(y,x%y):x};print(f(1)-f(C)-f(D)+f(C*D/g(C,D)))
//  [swift]
func gcd(x: Int, _ y: Int) -> Int {
    if y == 0 {
        return x
    } else {
        return gcd(y, x%y)
    }
}
func lcm(x: Int, _ y: Int) -> Int {
    return x * y / gcd(x, y)
}
let input = readLine()!.characters.split(" ").map{Int(String($0))!}
let (A, B, C, D) = (input[0], input[1], input[2], input[3])
let tmp = lcm(C, D)
let tmp1 = B/C - (A-1)/C        // AからBまでのうちCで割り切れる数の個数
let tmp2 = B/D - (A-1)/D        // AからBまでのうちDで割り切れる数の個数
let tmp3 = B/tmp - (A-1)/tmp    // AからBまでのうちCとD両方で割り切れる数の個数
let tmp4 = tmp1 + tmp2 - tmp3   // AからBまでのうちCもしくはDで割り切れる数の個数
print(B - A + 1 - tmp4)
//  [swift]
func gcd(x: Int, _ y: Int) -> Int {
    if y == 0 {
        return x
    } else {
        return gcd(y, x%y)
    }
}
let input = readLine()!.characters.split(" ").map{Int(String($0))!}
let (A, B, C, D) = (input[0]-1, input[1], input[2], input[3])
let tmp = C*D / gcd(C, D)
let tmp1 = B/C - A/C            // (A...B)でCで割り切れる数の個数
let tmp2 = B/D - A/D            // (A...B)でDで割り切れる数の個数
let tmp3 = B/tmp - A/tmp        // (A...B)で(C AND D)で割り切れる数の個数
let tmp4 = tmp1 + tmp2 - tmp3   // (A...B)で(C XOR D)で割り切れる数の個数
print(B - A - tmp4)             // (A...B)で(C AND D)で割り切れない数
//  [swift]
let input = readLine()!.characters.split(" ").map{Int(String($0))!}
let (A, B, C, D) = (input[0], input[1], input[2], input[3])
let tmp = lcm(C, D)
let tmp1 = B/C - (A-1)/C        // AからBまでのうちCで割り切れる数の個数
let tmp2 = B/D - (A-1)/D        // AからBまでのうちDで割り切れる数の個数
let tmp3 = B/tmp - (A-1)/tmp    // AからBまでのうちCとD両方で割り切れる数の個数
let tmp4 = tmp1 + tmp2 - tmp3   // AからBまでのうちCもしくはDで割り切れる数の個数
print(B - A + 1 - tmp4)
//  [typescript]
const input=require('fs').readFileSync('/dev/stdin','utf8').split(/[\s]/);let input_i=-1;const tn=():number=>{input_i++;return Number(input[input_i])};const tnn=(n:number):number[]=>{const a=[];for(let i=0;i<n;i++){a.push(tn())}return a};const ts=():string=>{input_i++;return String(input[input_i])};const tss=(n:number):string[]=>{const a=[];for(let i=0;i<n;i++){a.push(ts())}return a};const to=(...arg)=>{console.log(...arg)};const abs=(a)=>{return Math.abs(a)};const min=(...a)=>{return Math.min(...a)};const max=(...a)=>{return Math.max(...a)};const floor=(a)=>{return Math.floor(a)};const asc=(ar:number[])=>{const t=[...ar];return ar.sort((a,b)=>{return a-b})};const desc=(ar:number[])=>{const t=[...ar];return t.sort((a,b)=>{return b-a})};const sw=(a,arr:any[],op:'=='|'>='|'>'|'<='|'<'='==')=>{for(let i=0;i<arr.length-1;i+=2){if(eval(a+op+arr[i])){return arr[i+1]}}return arr[arr.length-1]};const near=(n:number,arr:number[]):number=>{let ne=arr[0],ni=0;for(let i=1;i<arr.length;i++){if(Math.abs(n-ne)>Math.abs(n-arr[i])){ne=arr[i];ni=i}}return ni};const deduplicate=(a:any[]):any[]=>{return Array.from(new Set(a))};const gcd=(x,y)=>{while(y){[x,y]=[y,x%y]}return x};
const main=()=>{
  let [a,b,c,d]=tnn(4)
  a=a--
  let lcm=c*d/gcd(c,d)
  to(b-floor(b/c)+floor(b/d)-floor(b/lcm)-(a-floor(a/c)+floor(a/d)-floor(a/lcm)))
}
main()