Problem:
Score : 300 points

Problem Statement

You are given four integers A, B, C, and D. Find the number of integers between A and B (inclusive) that can be evenly divided by neither C nor D.

Constraints

1\leq A\leq B\leq 10^{18}

1\leq C,D\leq 10^9

All values in input are integers.

Input

Input is given from Standard Input in the following format:

A B C D

Output

Print the number of integers between A and B (inclusive) that can be evenly divided by neither C nor D.

Sample Input 1

4 9 2 3

Sample Output 1

2

5 and 7 satisfy the condition.

Sample Input 2

10 40 6 8

Sample Output 2

23

Sample Input 3

314159265358979323 846264338327950288 419716939 937510582

Sample Output 3

532105071133627368

Solution in JavaScript (node.js v5.12) (judge verdict: Wrong Answer)

function main(input) {
  const inputList = input.split(/\s/).map(inp => formatNum(inp));
  const test = 1000;
  const A = inputList[0] - 1;
  const B = inputList[1];
  const C = inputList[2];
  const D = inputList[3];
  
  const retAC = Math.floor(A / C);
  const retAD = Math.floor(A / D);
  const retACD = Math.floor(A / getLCM(C, D));
  const retBC = Math.floor(B / C);
  const retBD = Math.floor(B / D);
  const retBCD = Math.floor(B / getLCM(C, D));
  const retB = B - (retBC + retBD - retBCD);
  const retA = A - (retAC + retAD - retACD);
  // memo:値の取り扱う範囲を理解すること
  console.log(retB - retA);
};

// 文字列を数値に変換
function formatNum(str) {
  return Number(str);
};

// 整数aと整数bの最小公倍数を求める
function getLCM(a, b) {

	// aの素因数リストを取得
	var aPrimeList = getPrimeList(a);

	// bの素因数リストを取得
	var bPrimeList = getPrimeList(b);

	// 最小公倍数を保存する変数
	var lcm = 1;

	var i, j;

	// 共通の因数を保存する配列
	var list = new Array();

	// 共通の因数を保存し、掛け合わせる
	for (i = 0;i < aPrimeList.length;i++) {

		// bの因数リストを走査
		for (j = 0;j < bPrimeList.length;j++) {

			// aの因数がbにも含まれていたら共通因数の処理
			if (aPrimeList[i].num == bPrimeList[j].num) {

				// 因数の指数のうち大きな方を掛け合わせる
				if (aPrimeList[i].r > bPrimeList[j].r) {
					for (k = 0;k < aPrimeList[i].r;k++) {
						lcm *= aPrimeList[i].num;
					}
				} else {
					for (k = 0;k < bPrimeList[j].r;k++) {
						lcm *= aPrimeList[i].num;
					}
				}

				// 共通因数配列に追加
				list.push(aPrimeList[i].num);

			}
		}

	}

	// aの素因数分解リストから共通因数でない因数を抽出し掛け合わせる
	for (i = 0;i < aPrimeList.length;i++) {

		var flg = false;

		for (j = 0;j < list.length;j++) {
			if (aPrimeList[i].num == list[j]) {
				flg = true;
			}
		}

		if (!flg) {
			for (k = 0;k < aPrimeList[i].r;k++) {
				lcm *= aPrimeList[i].num;
			}
		}

	}

	// bの素因数分解リストから共通因数でない因数を抽出し掛け合わせる
	for (i = 0;i < bPrimeList.length;i++) {

		var flg = false;

		for (j = 0;j < list.length;j++) {
			if (bPrimeList[i].num == list[j]) {
				flg = true;
			}
		}

		if (!flg) {
			for (k = 0;k < bPrimeList[i].r;k++) {
				lcm *= bPrimeList[i].num;
			}
		}

	}

	return lcm;

}

// numを素因数分解し結果を因数と指数のオブジェクト配列として返す
function getPrimeList(num) {

	var list = new Array();

	if (num < 1) {
		return null;
	}

	var i;

	// 平方根を素因数候補の最大値とする
	var r = Math.floor(Math.sqrt(num));

	for (i = 2;i <= r;i++) {

		// 候補で割り切れたら素因数として追加
		if ((num % i) == 0) {

			var n = 0;

			// 割り切れる回数を指数として記録
			do {

				n++;

				num = num / i;

			} while ((num % i) == 0);

			// 素因数オブジェクト作成
			var item = new Object();

			// 値と指数をプロパティとして記録
			item.num = i;
			item.r = n;

			// 配列にオブジェクトを記録
			list.push(item);

		}

	}

	// 最後に残った素因数を追加
	if (num > r) {

		var item = new Object();

		item.num = num;
		item.r = 1;

		list.push(item);

	}

	// 結果を返す
	return list;

}

main(require("fs").readFileSync("/dev/stdin", "utf8"));