สมมติว่าเรามีอาร์เรย์ A ของจำนวนเต็มบวก เราสามารถพูดได้ว่าอาร์เรย์เป็นกำลังสอง ถ้าสำหรับทุกคู่ขององค์ประกอบที่อยู่ติดกัน ผลรวมของมันเป็นกำลังสองสมบูรณ์ เราต้องหาจำนวนการเรียงสับเปลี่ยนของ A ที่เป็นกำลังสอง การเรียงสับเปลี่ยนสองแบบ A1 และ A2 จะไม่เหมือนกันก็ต่อเมื่อมีดัชนี i บางอย่างที่ทำให้ A1[i] ไม่เหมือนกับ A2[i]
ดังนั้น หากอินพุตเป็น [3,30,6] เอาต์พุตจะเป็น 2 เนื่องจากเรามีการเรียงสับเปลี่ยนสองแบบ เช่น [3,6,30], [30,6,3]
เพื่อแก้ปัญหานี้ เราจะทำตามขั้นตอนเหล่านี้ -
-
กำหนดฟังก์ชัน isSqr() ซึ่งจะใช้เวลา n
-
x :=รากที่สองของ n
-
คืนค่า จริง เมื่อ (x * x) เหมือนกับ n
-
-
กำหนดฟังก์ชัน Solve() ซึ่งจะใช้อาร์เรย์ a, idx,
-
ถ้า idx เท่ากับขนาด a แล้ว −
-
(เพิ่มจำนวนขึ้น 1)
-
กลับ
-
-
กำหนดการเยี่ยมชมหนึ่งชุด
-
สำหรับการเริ่มต้น i :=idx เมื่อฉัน <ขนาดของ a อัปเดต (เพิ่ม i ขึ้น 1) ทำ -
-
ถ้า (idx เหมือนกับ 0 หรือ isSqr(a[idx - 1] + a[i])) และ a[i] ไม่ได้ถูกเข้าชม −
-
สลับ (a[idx], a[i])
-
แก้(a, idx + 1)
-
สลับ (a[idx], a[i])
-
ใส่ a[i] เข้าไป
-
-
-
-
จากวิธีหลัก ให้ทำดังนี้ −
-
นับ :=0
-
แก้(a, 0)
-
จำนวนคืน
ให้เราดูการใช้งานต่อไปนี้เพื่อความเข้าใจที่ดีขึ้น -
ตัวอย่าง
#include <bits/stdc++.h>
using namespace std;
typedef long long int lli;
class Solution {
public:
int count;
bool isSqr(lli n){
lli x = sqrt(n);
return x * x == n;
}
void solve(vector<int>& a, int idx){
if (idx == a.size()) {
count++;
return;
}
set<int> visited;
for (int i = idx; i < a.size(); i++) {
if ((idx == 0 || isSqr(a[idx - 1] + a[i])) &&
!visited.count(a[i])) {
swap(a[idx], a[i]);
solve(a, idx + 1);
swap(a[idx], a[i]);
visited.insert(a[i]);
}
}
}
int numSquarefulPerms(vector<int>& a){
count = 0;
solve(a, 0);
return count;
}
};
main(){
Solution ob;
vector<int> v = {3,30,6};
cout << (ob.numSquarefulPerms(v));
} อินพุต
{3,30,6} ผลลัพธ์
2