牛客 215E 黃魔法師 題解

下蛋爷發表於2024-05-04

Description

給出 \(n, k\),求一個長度為 \(n\) 的陣列 \(a\), 滿足有恰好 \(k\) 對數對 \((i, j) (1 \leq i < j \leq n)\) 滿足 \(a_i + a_j\) 為完全平方數。如果不存在,輸出 \(-1\)

link

Solution

顯然如果 \(k>\binom{n}{2}\) 就一定無解。

構造時會發現肯定要儘量弄成相同的然後進行微調,那麼設 \(m\) 為最大的數滿足 \(\binom{m}{2}\leq k\)\(r=k-\binom{m}{2}\)

這個時候直接選 \(m\)\(2\) 會發現多出來的 \(r\) 很難微調,因為這個時候要是調整加數的話最小就是增加 \(m\) 了。

這時可以把 \(m\) 個數拆成 \(r\)\(A\)\(m-r\)\(B\),然後找 \(1\)\(C\) 使得 \(A+B,2A,2B,A+C\) 均為完全平方數並且其他的都不是完全平方數,剩下多的 \(n-m-1\)\(D\) 只要隨便找一個數使得加出來不是完全平方數即可。

經列舉 \(A=2,B=98,C=7,D=1\) 可以滿足條件。

時間複雜度:\(O(n)\)

Code

#include <bits/stdc++.h>

#define int int64_t

const int kMaxN = 1e5 + 5;

int n, k, m, r;

bool check(int x) {
  int y = sqrtl(x);
  for (; y * y > x; --y) {}
  for (; (y + 1) * (y + 1) <= x; ++y) {}
  return x == y * y;
}

void dickdreamer() {
  std::cin >> n >> k;
  if (k > n * (n - 1) / 2) return void(std::cout << "-1\n");
  for (m = 1; m * (m + 1) / 2 <= k; ++m) {}
  if (n == m) {
    for (int i = 1; i <= n; ++i) std::cout << "2 ";
    return;
  }
  r = k - m * (m - 1) / 2;
  for (int i = 1; i <= r; ++i) std::cout << "2 ";
  for (int i = 1; i <= m - r; ++i) std::cout << "98 ";
  std::cout << "7 ";
  for (int i = 1; i <= n - m - 1; ++i) std::cout << "1 ";
}

int32_t main() {
#ifdef ORZXKR
  freopen("in.txt", "r", stdin);
  freopen("out.txt", "w", stdout);
#endif
  std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
  int T = 1;
  // std::cin >> T;
  while (T--) dickdreamer();
  // std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
  return 0;
}

相關文章