unittest
{
	assert( [ "3 24" ].parse.expand.solve == 2 );
	assert( [ "5 1" ].parse.expand.solve == 1 );
	assert( [ "1 111" ].parse.expand.solve == 111 );
	assert( [ "4 972439611840" ].parse.expand.solve == 206 );
	
	assert( [ "190000000000 972439611841" ].parse.expand.solve == 1 );		// 追加ケース
}



import std.algorithm;
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 np = input.front.split.to!( long[] );
	return tuple( np[ 0 ], np[ 1 ] );
}

auto solve( long n, long p )
{
	// pを素因数分解して素因数ごとの個数をカウント
	auto gs = PrimeFactors( p ).group;
	
	// as全部に掛けられる個数の素因数があったら最大公約数を大きくできる
	auto ans = 1L;
	foreach( g; gs )
	{
		auto d = g[ 1 ] / n;
		if( 0 < d ) ans *= g[ 0 ] ^^ d;
	}
	return ans;
}

// 素数レンジ
struct Primes
{
	private static memo = appender( [ 2L, 3L ] );
	private size_t mi;
	private size_t pi;
	public bool empty(){ return false; }
	public long front(){ return memo.data[ mi ]; }
	public void popFront()
	{
		mi++;
		if( mi < memo.data.length ) return;
		LOOP: for( auto n = memo.data[ $ - 1 ] + 2;; n += 2 )
		{
			pi += ( memo.data[ pi ] ^^ 2 <= n );
			foreach( p; memo.data[ 0 .. pi ] )
			{
				if( n % p == 0 ) continue LOOP;
			}
			memo.put( n );
			break;
		}
	}
}

// 素因数分解レンジ
struct PrimeFactors
{
	private long n;
	private long f;
	private Primes ps;
	public this( long n ){ this.n = n; popFront(); }
	public bool empty(){ return ( f == 0 ); }
	public long front(){ return f; }
	public void popFront()
	{
		if( n <= 1 ) f = 0;
		else
		{
			while( n % ps.front != 0 ) ps.popFront;
			n /= ps.front;
			f  = ps.front;
		}
	}
}
