和的逆运算问题 | 豆包MarsCode AI刷题

65 阅读3分钟

题目分析

题目要求我们根据 n 个整数两两相加得到的 n(n - 1) / 2 个和,找出原来的 n 个整数。这是一个典型的数学问题,可以通过构建方程组来解决。

关键点在于:

  • 每个整数与其他整数相加会得到 n-1 个和。
  • 所有和的总和是 n 个整数的总和的 n-1 倍。
  • 通过这些和,我们需要反推出原来的 n 个整数。

解题思路

  1. 计算总和:首先计算所有和的总和,如果这个总和不能被 n-1 整除,则说明没有解,因为这意味着原始整数的总和无法满足条件。
  2. 确定第一个整数:由于每个整数都与其他整数相加,我们可以通过总和除以 n-1 来确定所有整数的总和,再减去任意一个和,得到第一个整数的值。
  3. 构建方程组:使用一个映射(map)来记录每个和出现的次数。通过第一个整数的值,我们可以计算出其他整数与第一个整数相加的和,并逐步确定其他整数的值。
  4. 验证和填充:对于每个可能的第一个整数的值,我们尝试构建完整的整数列表。如果成功,则返回这些整数;如果失败,则尝试下一个可能的值。

代码解析

#include <bits/stdc++.h>
using namespace std;

string solution(int n, vector<int> sums) {
  int sum = 0;
  for (auto s : sums)
    sum += s; // 计算所有和的总和

  if (sum % (n - 1) != 0)
    return "Impossible"; // 如果总和不能被 n-1 整除,则返回 "Impossible"

  vector<int> ans(n);
  sort(sums.begin(), sums.end()); // 对和进行排序,方便后续处理

  for (int i = -abs(sums[0]); i <= abs(sums[0]); i++) { // 尝试所有可能的第一个整数值
    ans[0] = i;
    map<int, int> p;
    for (auto s : sums)
      p[s]++; // 记录每个和出现的次数

    int idx = 1;
    for (auto [k, v] : p) { // 遍历每个和
      if (!v)
        continue;
      while (p[k]) { // 当和还有剩余时
        ans[idx] = k - ans[0]; // 计算当前整数的值
        int t;
        for (t = 0; t < idx; t++) { // 验证当前整数是否满足其他和
          if (p[ans[idx] + ans[t]])
            p[ans[idx] + ans[t]]--;
          else
            break;
        }
        if (t == idx)
          idx++; // 如果验证成功,则移动到下一个整数
        else
          break; // 如果验证失败,则尝试下一个可能的第一个整数值
      }
    }
    if (idx == n)
      break; // 如果找到了所有整数,则退出循环
  }

  string res = "";
  for (int i = 0; i < n - 1; i++)
    res = res + to_string(ans[i]) + " "; // 构建结果字符串

  return res + to_string(ans[n - 1]); // 返回最终结果
}

int main() {
  // 测试用例
  vector<int> sums1 = {1269, 1160, 1663};
  vector<int> sums2 = {1, 1, 1};
  vector<int> sums3 = {226, 223, 225, 224, 227, 229, 228, 226, 225, 227};
  vector<int> sums4 = {-1, 0, -1, -2, 1, 0, -1, 1, 0, -1};
  vector<int> sums5 = {79950, 79936, 79942, 79962, 79954,
                       79972, 79960, 79968, 79924, 79932};

  // 输出测试结果
  cout << (solution(3, sums1) == "383 777 886") << endl;
  cout << (solution(3, sums2) == "Impossible") << endl;
  cout << (solution(5, sums3) == "111 112 113 114 115") << endl;
  cout << (solution(5, sums4) == "-1 -1 0 0 1")