class Solution {
 public:
  int numSquarefulPerms(vector<int>& nums) {
    int ans = 0;
    ranges::sort(nums);
    dfs(nums, vector<bool>(nums.size()), {}, ans);
    return ans;
  }
 private:
  void dfs(vector<int>& nums, vector<bool>&& used, vector<int>&& path,
           int& ans) {
    if (path.size() > 1 && !isSquare(path.back() + path[path.size() - 2]))
      return;
    if (path.size() == nums.size()) {
      ++ans;
      return;
    }
    for (int i = 0; i < nums.size(); ++i) {
      if (used[i])
        continue;
      if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1])
        continue;
      used[i] = true;
      path.push_back(nums[i]);
      dfs(nums, std::move(used), std::move(path), ans);
      path.pop_back();
      used[i] = false;
    }
  }
  bool isSquare(int num) {
    const int root = sqrt(num);
    return root * root == num;
  }
};