diff --git a/Mathematics/Fundamentals/HackerRank/Claude/Easy/Best Divisor/BestDivisor.html b/Mathematics/Fundamentals/HackerRank/Claude/Easy/Best Divisor/BestDivisor.html new file mode 100644 index 00000000..6b914d66 --- /dev/null +++ b/Mathematics/Fundamentals/HackerRank/Claude/Easy/Best Divisor/BestDivisor.html @@ -0,0 +1,2238 @@ + + +
+ + ++ √n約数列挙+桁和比較 による O(√n) 実装 +
+ +
+ Kristenは数字の各桁の和(桁和)で数の良し悪しを判定します。与えられた整数
+ n
+ の約数のうち、以下の基準で「最良」のものを見つけてください:
+
Input:
+12
+ Output:
+6
+ + 説明: 12の約数は {1, 2, 3, 4, 6, 12}。各桁和は {1, 2, 3, 4, + 6, 3}。最大桁和6を持つ約数は 6。 +
+max() と
+ sum() を活用
+ def findBestDivisor(n: int) -> int:
+ """
+ 最良の約数を見つける(競技プログラミング最適化版)
+
+ Time Complexity: O(√n)
+ Space Complexity: O(d) where d is number of divisors
+ """
+ divisors = []
+ i = 1
+
+ # √n まで探索して約数をペアで収集
+ while i * i <= n:
+ if n % i == 0:
+ divisors.append(i)
+ # 平方数でない場合のみペアを追加
+ if i != n // i:
+ divisors.append(n // i)
+ i += 1
+
+ # 桁和が最大、同値なら最小値を選択
+ # タプル比較: (桁和大, 値小) = (sum, -divisor)
+ return max(divisors, key=lambda x: (sum(int(d) for d in str(x)), -x))
+
+
+# 使用例
+if __name__ == '__main__':
+ n = int(input().strip())
+ result = findBestDivisor(n)
+ print(result)
+
+ フローの説明:
+ 1. 入力 n を受け取り、空の約数リスト divisors と i=1 で初期化
+ 2. i×i ≤ n の間ループ:n を i で割り切れるか判定
+ 3. 割り切れる場合、i と n//i を約数リストに追加(i≠n//i の場合のみペア追加)
+ 4. i を1増やしてループ継続
+ 5. ループ終了後、約数リストから桁和が最大(同値なら最小値)の約数を選択
+ 6. 結果を返して終了
+
| + 項目 + | ++ 本実装(√n列挙) + | ++ 代替手法(全探索) + | +
|---|---|---|
| + 時間計算量 + | +
+ O(√n)
+
+ √n までループ + O(d log d) 桁和計算
+
+ |
+
+ O(n)
+
+ 1 から n まで全探索
+
+ |
+
| + 空間計算量 + | +
+ O(d)
+
+ 約数リスト(d は約数の個数)
+
+ |
+
+ O(d)
+ 同じ
+ |
+
| + 実装コスト + | +
+ 中
+
+ √n 判定とペア追加が必要
+
+ |
+
+ 低
+ シンプルなループ
+ |
+
| + 制約 n≤105 での推奨度 + | +
+ ★★★★★
+
+ 最大√100000 ≈ 316 回のループで済む
+
+ |
+
+ ★★★☆☆
+
+ 100000回ループは許容範囲だが非効率
+
+ |
+
max()
+ のkey引数で、タプル比較
+ (桁和, -値)
+ により1パスで最良約数を選択
+ sum(int(d) for d in str(x))
+ でジェネレータ式とC実装のsumを活用
+ i != n // i
+ で重複を防ぐ(例:n=16 の場合 i=4 を2回追加しない)
+ n = 12 の場合:
+