https://codility.com/programmers/lessons/8
一番簡単な答えは、aとbの値を全部チェックすることですね. ただ a * b = Nなので、sqrt(N)以下のaにだけ関して調べて行けばいいということになります。
この方針で100%もらえてしまいます。
#include <math.h> int solution(int N)
{ int a;
int sqrtN = sqrt(N); int min = 2147483647; //the initial value for the min (INT_MAX).
for (a = 1; a <= sqrtN; a++){ if (N % a == 0){
int b = N / a;
min = a + b < min ? a + b : min;
}
}
return min * 2; }
しかし、この上のコードはあまり効率的ではありません。
sqrt(N)から1に向かって下って'a'をチェックして行き、最初にN% a == 0になった時の値で答えを計算して返すのがより良い方法です。(N / a = bですから(a * N / a) * 2を返せば良いですね)。
何故これで良いのか考えてみましょう。まず 1 <= x < y <= sqrt(N) というようなxとyの値を考えましょう。xとyはどちらも整数です。
もし、ここで下記のことが言えれば、yが大きい方がかならず外周が小さいと言えますね。
2 * (y + N / y) < 2 * (x + N / x)
式を一つずつ変形して行きましょう。
(y + N / y) < (x + N / x)
(y + N / y) - (x + N / x) < 0
(y - x) + (N / y - N / x) < 0
(y - x) < -(N / y - N / x)
(y - x) < -N / y + N / x
(y - x) < N / x - N / y
(y - x) < Ny - Nx / xy
(y - x) < N(y - x) / xy
1 < N / xy
ここで、1 <= x < y <= sqrt(N)なのですから、0 < xy < Nとなりますね。(yが最大値のsqrt(N)でもxはそれより小さいため、sqrt(N) * sqrt(N) = Nよりxyは小さくなりますね)
つまり上の1 < N / xyは成り立つことがわかります。最初の2 * (y + N / y) < 2 * (x + N / x)は正しいということですね。
ということは'a'の値を探す時に、sqrt(N)以下の大きい方から見ていって1に近づいて行き、最初のN % a == 0が見つかった時点で、一番小さい外周を返すaもbも確定したと考えてよいということになります。
これで100%のスコアがもらえます。
#include <math.h> int solution(int N)
{ int a;
int sqrtN = sqrt(N);
for (a = sqrtN; a >= 1; a--){
if (N % a == 0){
break;
}
}
return (a + N / a) * 2;
}
0 件のコメント:
コメントを投稿