ここに私のコメントを要約して、新しい訪問者にとって理解しやすいようにします.
他の人が指摘したように、シーケンス Aは単なる正方形のシーケンスです。OPが彼のコメントを通じて明らかにしたように、シーケンスBは常に変化します。
OPの問題の言い直しは
数列の各項を計算するよりも、増加する数列の最初の二乗を決定する高速な方法はありますか?
確かに、あります。明らかなアイデアは、シーケンスに対する正方形の成長率に関する洞察に基づいて、いくつかの項の計算を「スキップ」する方法を考案することです。しかし、任意のシーケンスに関する洞察をプログラムで導き出すのは困難です。
より堅牢な解決策は、次の最小ゼロを見つけるように問題を再定式化することです。
B(x) - x^2 = 0
そのために、役立つルート検索アルゴリズムが存在する可能性があります。最小のゼロを見つける必要がない場合は、さらに簡単です。任意のルート検索アルゴリズムを実装し、アルゴリズムがゼロに収束するのを監視しx^2
、再定式化を補償するために追加します。
編集
(コメント ボックスが狭すぎて、返信できませんでした。)
「二分」と言ったとき、実際には「二分探索」を意味していました。これには上限が必要なため、問題には実際には当てはまりません。
あなたはおそらくすでにこれを正確に考えているでしょうが、最初に単純なアルゴリズムを提供させてください。
- 計算し
B(1)
ます。1692
それが(正方形ではない)だと言ってください。
- 計算し
B(2)
ます。1707
それが(正方形ではない)だと言ってください。
- を計算し、それを「デルタ
B(2)-B(1)
」と呼びます。これは の成長率の単純な推定と考えてください。もちろん、それはほぼ確実に間違っていますが、ここで目指しているのは、用語をスキップする方法だけです。それが後で最適化されるものです。 1707-1692
15
B
- より大きい次の平方は
1707
? 式 は(floor(sqrt(1707))+1)^2
、 をもたらし1764
ます。
- その正方形にたどり着くには、いくつの項をスキップする必要がありますか? 別の式 から
(1764-1707)/15
が得られ3.8
、これを に丸めることができ4
ます。
- 計算し
B(2+4) = B(6)
ます。
- より小さい場合は
1764
、続行する必要があります。しかし、この場合、3 つの項を計算する必要がなくなりました。正確にどのように継続するかは、別の選択肢にすぎません。B(7)
計算してステップ 3 (B(7)-B(6)
新しいデルタとして計算) に進むことができます。(B(6)-B(2))/4
ステップ 3 (新しいデルタとして計算) に直接進むことができます。(の可能な関数を特徴付けずに、何が最善かを本当に知ることはできませんB
。)
- より大きい場合は
1764
、戻る必要があります。繰り返しますが、多くの方法があります。二分探索は、実際には単純で合理的な方法です。と の間にB(4)
直接あるため、計算します。未満の場合は、 を試してください。より大きい場合は、 を試してください。どちらかが一致しない場合は、 から始めます。二分探索では、せいぜい計算を行うだけです。B(2)
B(6)
1764
B(5)
1764
B(3)
B(7)
log(N)
それで、それはかなりのように聞こえますよね?いくつかの計算をスキップするかlog(N)
、せいぜい実行します。(または、これに対するさらに優れた最適化を見つけることができます。) しかし、明らかに、これらのデルタ、射影、二分探索などを見つけるために余分な計算を行っているため、それほど単純ではありません。正方形は非常にゆっくりと成長するため (正方形の間に非常に多くの整数があります)、大きな整数、または非常に複雑なシーケンスを扱っている場合、そのようなアルゴリズムは「線形検索」(すべての項を計算する) を打ち負かすだけだと思いますB
(ただしB
、常に増加する必要があるため、どれだけ複雑か)シーケンスは本当にありますか?) キーは、すべてのシーケンスに適合する特性を見つけることです。
あなたのアプリケーションが何であるかはまだわかりませんが、この時点で、実際のデータセットに対して (線形検索と比較して) 試してベンチマークすることもできます。これにより、実際に利益が得られるかどうか、および最適化により多くの時間を投資する必要があるかどうかがすぐにわかります。そして、すべての理論的な計算、特徴付けシーケンスなどを実行しようとするよりも高速です。