unittest
{
	assert( [ "4 9 2 3" ].parse.expand.solve == 2 );
	assert( [ "10 40 6 8" ].parse.expand.solve == 23 );
	assert( [ "314159265358979323 846264338327950288 419716939 937510582" ].parse.expand.solve == 532105071133627368 );
}



import std.conv;
import std.range;
import std.stdio;
import std.typecons;

void main()
{
	stdin.byLineCopy.parse.expand.solve.writeln;
}

auto parse( Range )( Range input )
if( isInputRange!Range && is( ElementType!Range == string ) )
{
	auto abcd = input.front.split.to!( long[] );
	return tuple( abcd[ 0 ], abcd[ 1 ], abcd[ 2 ], abcd[ 3 ] );
}

auto solve( long a, long b, long c, long d )
{
	// 1 以上 a 未満で c と d で割り切れるものの個数を計算
	auto ac = ( a - 1 ) / c;
	auto ad = ( a - 1 ) / d;
	auto acd = ac + ad - ( ( a - 1 ) / lcm( c, d ) );
	
	// 1 以上 b 以下で c と d で割り切れるものの個数を計算
	auto bc = b / c;
	auto bd = b / d;
	auto bcd = bc + bd - ( b / lcm( c, d ) );
	
	// a 以上 b 以下で c と d で割り切れないものの個数を計算
	return ( b + 1 - a ) - ( bcd - acd );
}

// 最小公倍数
auto lcm( long x, long y )
{
	import std.numeric : gcd;
	return x * y / x.gcd( y );
}
