torus711 のアレ

主に競技プログラミングの問題について書きます.PC 以外だと数式が表示されないかもしれないです

AtCoder Regular Contest 106, A : 106

問題概要

 正整数 $N$ が与えられる.$3^A + 5^B = N$ を満たす整数の組 $( A, B )$ を一つ見つけよ.存在しない場合は代わりに $-1$ を出力せよ.

制約

  • $1 \leq N \leq 10^{ 18 }$

解法

 $A, B$ が指数の肩に乗っているため,$A, B$ を大きくしていくと $3^A, 5^B$ は指数的に大きくなります.また,一旦 $3^A > N$ や $5^B > N$ になるとその先に解はありません.つまり,$A, B$ はそれぞれ $O( \log N )$ 通りぐらいしか候補がありません.この範囲であれば組合せを全通り試してしまえる程度の個数なので,そのようにします.計算量としては,試すべき整数の対が $O( ( \log N )^2 )$ 個あるので,$O( ( \log N )^2 )$ 時間になります.

コード

main = do
	n <- readInteger
	let
		res = do
			a :: Int <- takeWhile ( \a -> 3 ^ a <= n ) [ 1 .. ]
			b :: Int <- takeWhile ( \b -> 5 ^ b <= n ) [ 1 .. ]
			guard $ 3 ^ a + 5 ^ b == n
			return ( a, b )
	if null res
		then print (-1)
		else uncurry ( printf "%d %d\n" ) $ head res