แนวคิด
สำหรับจำนวนเต็ม X ที่กำหนด งานของเราคือกำหนดค่าสูงสุด N เพื่อให้ผลรวมของจำนวนธรรมชาติ N ตัวแรกไม่ควรเกิน X
อินพุต
X = 7
ผลลัพธ์
2
2 คือค่าสูงสุดที่เป็นไปได้ของ N เนื่องจากสำหรับ N =3 ผลรวมของอนุกรมจะเกิน Xi.e 1^2 + 2^2 + 3^2 =1 + 4 + 9 =14
อินพุต
X = 27
ผลลัพธ์
3
3 คือค่าที่เป็นไปได้สูงสุดของ N เพราะสำหรับ N =4 ผลรวมของอนุกรมจะเกิน X.e 1^2 + 2^2 + 3^2 + 4^2 =1 + 4 + 9 + 16 =30
วิธีการ
วิธีแก้ปัญหาง่ายๆ − ในที่นี้ วิธีแก้ปัญหาง่ายๆ คือดำเนินการวนรอบจาก 1 จนถึงค่าสูงสุด N เพื่อให้ S(N) ≤ X ในกรณีนี้ S(N) ถูกเรียกว่าเป็นผลรวมของกำลังสองของจำนวนธรรมชาติ N ตัวแรก ด้วยเหตุนี้ ผลรวมกำลังสองของจำนวนธรรมชาติ N ตัวแรกจึงถูกกำหนดโดยสูตร S(N) =N * (N + 1) * (2 * N + 1) / 6
ควรสังเกตว่าความซับซ้อนของเวลาของวิธีการนี้คือ O(N)
แนวทางที่มีประสิทธิภาพ − เราสามารถใช้โซลูชันอื่นที่มีประสิทธิภาพซึ่งอิงตามแนวทางการค้นหาแบบไบนารี
เราปฏิบัติตามอัลกอริทึมด้านล่างซึ่งอธิบายทีละขั้นตอน -
-
เริ่มการค้นหาไบนารีในอาร์เรย์ที่ใหญ่กว่าและรับค่ากลางเป็น (ต่ำ + สูง) / 2
-
จะเห็นได้ว่าหากค่าจากอาร์เรย์ทั้งสองมีค่าเท่ากัน องค์ประกอบจะต้องอยู่ทางด้านขวา ดังนั้นให้ทำเครื่องหมายที่ระดับต่ำเป็นระดับกลาง
-
มิฉะนั้นให้ทำเครื่องหมายสูงเป็นระดับกลางเนื่องจากองค์ประกอบต้องอยู่ในด้านซ้ายของอาร์เรย์ที่ใหญ่กว่าหากองค์ประกอบกลางไม่เหมือนกัน
ควรสังเกตว่าความซับซ้อนของเวลาของวิธีการนี้คือ O(log N)
ตัวอย่าง
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std; #define ll long long // Shows function to return the sum of the squares // of first N1 natural numbers ll squareSum(ll N1){ ll sum1 = (ll)(N1 * (N1 + 1) * (2 * N1 + 1)) / 6; return sum1; } // Shows function to return the maximum N such that // the sum of the squares of first N // natural numbers is not more than X ll findMaxN(ll X){ ll low1 = 1, high1 = 100000; int N1 = 0; while (low1 <= high1) { ll mid1 = (high1 + low1) / 2; if (squareSum(mid1) <= X) { N1 = mid1; low1 = mid1 + 1; } else high1 = mid1 - 1; } return N1; } // Driver code int main(){ ll X = 27; cout << findMaxN(X); return 0; }
ผลลัพธ์
3