Problem:
Score : 400 points

Problem Statement

You are given integers N and M.

Consider a sequence a of length N consisting of positive integers such that a_1 + a_2 + ... + a_N = M. Find the maximum possible value of the greatest common divisor of a_1, a_2, ..., a_N.

Constraints

All values in input are integers.

1 \leq N \leq 10^5

N \leq M \leq 10^9

Input

Input is given from Standard Input in the following format:

N M

Output

Print the maximum possible value of the greatest common divisor of a sequence a_1, a_2, ..., a_N that satisfies the condition.

Sample Input 1

3 14

Sample Output 1

2

Consider the sequence (a_1, a_2, a_3) = (2, 4, 8). Their greatest common divisor is 2, and this is the maximum value.

Sample Input 2

10 123

Sample Output 2

3

Sample Input 3

100000 1000000000

Sample Output 3

10000

Solution in OCaml (4.02.3) (judge verdict: Time Limit Exceeded)

open Printf open Scanf
module MyInt = struct let (+) = (+) let (-) = (-) let (/) = (/) let ( * ) = ( * ) let (mod) = (mod) let (%) = (mod) let (+=) r v = r := !r + v let (-=) r v = r := !r - v let ( *=) r v= r := !r * v let (/=) r v = r := !r / v let abs v = abs v let (land),(lor),(lxor),lnot,(lsl),(lsr),(asr) = (land),(lor),(lxor),lnot,(lsl),(lsr),(asr) let min_int,max_int = min_int,max_int end
module MyInt64 = struct
	let (+$) = (+) let (-$) = (-) let (/$) = (/) let ( *$) = ( * ) let (+) p q = Int64.add p q let (-) p q = Int64.sub p q let ( * ) p q = Int64.mul p q let (/) p q = Int64.div p q let (+=) r v = r := !r + v let (-=) r v = r := !r - v let ( *=) r v= r := !r * v let (/=) r v = r := !r / v let labs p = if p < 0L then -1L*p else p let (~|) p = Int64.to_int p let (~~|) p = Int64.of_int p let input_i64_array n = Array.init (~| n) (fun _ -> Scanf.scanf " %Ld" (fun v -> v)) let get_i64 _ = Scanf.scanf " %Ld" (fun v -> v) let get_2_i64 _ = Scanf.scanf " %Ld %Ld" (fun u v -> u,v) let get_3_i64 _ = Scanf.scanf " %Ld %Ld %Ld" (fun u v w -> u,v,w) let get_4_i64 _ = Scanf.scanf " %Ld %Ld %Ld %Ld" (fun u v w x -> u,v,w,x) let get_5_i64 _ = Scanf.scanf " %Ld %Ld %Ld %Ld %Ld" (fun u v w x y -> u,v,w,x,y) let print_i64_endline n = n |> Int64.to_string |> print_endline let (mod) m n = m - (m/n) * n let (%) = (mod) let rec gcd m n = match m,n with | m,0L -> m | m,n -> gcd n (m mod n) let lcm m n = (m*n) / gcd m n let rep from_ to_ fbod = let i,f = ref ~|from_,ref true in while !i <= ~|to_ && !f do match fbod ~~| !i with | `Break -> f := false | _ -> i := !i +$ 1; done let repb from_ to_ fbod = let i,f = ref ~|from_,ref true in while !i <= ~|to_ && !f do match fbod (~~| !i) with | `Break -> f := false | _ -> i := !i +$ 1 done; !f let repm from_ to_ m_init fbod = let i,f,m = ref ~|from_,ref true,ref m_init in while !i <= ~|to_ && !f do match fbod !m (~~| !i) with | `Break -> f := false | `Break_m m' -> (f := false; m := m') | `Ok m' -> (i := !i +$ 1; m := m') done; !m let repmb from_ to_ m_init fbod = let i,f,m = ref ~|from_,ref true,ref m_init in while !i <= ~|to_ && !f do match fbod (~~| !i) !m with | `Break -> f := false | `Break_m m' -> (f := false; m := m') | `Ok m' -> (i := !i +$ 1; m := m') done; (!m,!f) let string_of_list ?(separator=" ") f ls = let rec f0 a s = match a with | [] -> s | [h] -> s ^ (f h) ^ separator | h::t -> f0 t (s ^ (f h) ^ separator) in f0 ls "" let char_list_of_string str = let rec f0 i a = if i<0 then a else f0 (i-$1) (str.[i]::a) in f0 (String.length str -$ 1) [] let string_of_char_list ls = List.fold_left (fun u v -> u ^ (String.make 1 v)) "" ls
	let (@@@) = (@) let (@) a i = a.(~|i) let (<@) a (i,v) = a.(~|i) <- v
	let ceildiv m n = (m+n-1L) / n
	let abs v = Int64.abs v let (land),(lor),(lxor),lnot,(lsl),(lsr),(asr) = let open Int64 in (logand),(logor),(logxor),lognot,(fun u v -> shift_left u (~|v)),(fun u v -> shift_right u (~|v)),(fun u v -> shift_right_logical u (~|v)) let min_int,max_int = Int64.min_int,Int64.max_int let get_string _ = scanf " %s" (fun v -> v)
	let i32,i64 = Int64.to_int,Int64.of_int let alen a = i64 @@ Array.length a
	let dump_array a = a |> Array.to_list |> string_of_list Int64.to_string |> print_endline let i32_get_int _ = Scanf.scanf " %d" (fun v -> v) let i32_get_2_ints _ = Scanf.scanf " %d %d" (fun u v -> u,v) let i32_get_3_ints _ = Scanf.scanf " %d %d %d" (fun u v w -> u,v,w) let i32_get_4_ints _ = Scanf.scanf " %d %d %d %d" (fun u v w x -> u,v,w,x) let i32_get_5_ints _ = Scanf.scanf " %d %d %d %d %d" (fun u v w x y -> u,v,w,x,y) let repi from_ to_ fbod = let i,f = ref from_,ref true in while !i <= to_ && !f do match fbod !i with | `Break -> f := false | _ -> i := !i +$ 1 done
end open MyInt64


let binary_search ng ok f =
	let rec f0 ng ok =
		if labs (ok - ng) <= 1L then ok
		else let mid = ng + (ok - ng) / 2L in if f mid then f0 ng mid else f0 mid ok
	in let d = if ng < ok then 1L else -1L
	in f0 ng ok
	(* in f0 (ng-1L*d) (ok+1L*d) *)
let () =
	let n,m = get_2_i64 0 in
	let d = m / n in
	repm 1L d 1L (fun u i ->
		let v = i * (n - 1L) in
		(* printf "%Ld - %Ld: mod %Ld = %Ld\n" m v i ((m-v) mod i); *)
		if (m-v) mod i = 0L then `Ok i else `Ok u
	)
	|> printf "%Ld\n"
	(* binary_search d 0L (fun i -> 
		let v = i * (n - 1L) in
		printf "%Ld - %Ld: mod %Ld = %Ld\n" m v i ((m-v) mod i);
		if (m-v) mod i = 0L then true else false
	)
	|> printf "%Ld\n" *)