1 条题解
-
0
自动搬运
来自洛谷,原作者为

寄风
现实中的你,是否很成功?搬运于
2025-08-24 23:14:43,当前版本为作者最后更新于2025-04-25 21:02:22,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
upd on 2025.6.5 修正了一个笔误,感谢
https://www.luogu.com.cn/user/225375场切并获得了首 A。
挺好的锻炼脑力题。
考虑推一个柿子,那么:
因为 ,所以 。
令 。
那么我们考虑把柿子拆开:
获得了这个之后我们该怎么做?
首先任意一个 我们都可以构造,设 ,那么我们让 的后 位都是 ,然后 就是 就可以了。
那么你发现 越小构造难度应该也是越小的。
那么先令 ,那么 ,显然是不可以的。
那么考虑让 。
那么我们获得了两个条件,就是 和 ;同时我们还获得了一个约束,就是 必须是 。
保险起见,我们先把 判掉,这个直接写个暴力找解即可。
那么因为 , 又大于 ,所以如果 的最高位和 的最高位相同我们是不好构造的。所以我们只能考虑从比 的最高位更高的位入手,设 的最高位是第 位,那么 和 的第 位都是 就可以了。
然后因为我们要保证 ,所以我们考虑将 的第 位置为 ,将 的第 位置为 就可以了。
那么剩下的位的话,因为二进制的按位考虑,所以我们可以将 的第 位到第 位都设成和 一样,这样子 就是 了。
那么我们再将 的第 位置 就可以满足 了。
的求法就是 。
这显然满足 。
总结下,就是构造 即可。
那么看上去对完了?这真的是对的吗?
这个正确性非常显然,用屁股都能想到。
写一发,结果。
其实这个做法是错的。
为啥会错呢?我们发现我们上面推导的一切,都有一个前提: 必须是 。而我们上面并没有保证 是 。
难道我们的努力白费了?
并不是。
我们考虑 是 的限制,也就是说 必须是 ,也就是说 必须是 。
在我们上面的构造中,我们保证了 和 。
所以如果 ,那么带回原式,我们的构造是有效的,,,,。
但是如果 我们的构造就无效了。
考虑将 与 进行微调,由于 ,所以如果我们将 和 的值同时减小 的话,并不会影响 的结果。
重新带回,当 时,,,,。
那么就做完了,不难证明大小关系依然满足 。
代码:
#include <bits/stdc++.h> using i64 = long long; using u64 = unsigned long long; using u32 = unsigned; using i128 = __int128; using u128 = unsigned __int128; i64 a, b, c, d; inline void debug() { std::cerr << "check:\n"; std::cerr << a * a + b * b + c * c + d * d << '\n'; std::cerr << (a ^ b ^ c ^ d) * (a ^ b ^ c ^ d) << '\n'; } int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr), std::cout.tie(nullptr); std::cin >> a; if (a == 1) { for (int b = a + 1; b <= 500; b++) { for (int c = b + 1; c <= 500; c++) { for (int d = c + 1; d <= 500; d++) { int xx = (a ^ b ^ c ^ d); if (a * a + b * b + c * c + d * d == xx * xx) { std::cout << b << ' ' << c << ' ' << d << '\n'; return 0; } } } } std::cout << -1 << '\n'; return 0; } //b=a+(1<<q),c=(1<<(q+1))+(1<<q)+1 int q = std::__lg(a); if (a % 2 == 0) { b = a + (1ll << q), c = (1ll << (q + 1)) + (1ll << q) + 1; d = (a * a + b * b + c * c - 1) / 2; //我靠,要保证 d 最后一位是 0 if (d % 2 == 0) { std::cout << b << ' ' << c << ' ' << d << '\n'; debug(); return 0; } assert(0); } else { b = a + (1ll << q) - 1, c = (1ll << (q + 1)) + (1ll << q); d = (a * a + b * b + c * c - 1) / 2; //我靠,要保证 d 最后一位是 0 if (d % 2 == 0) { std::cout << b << ' ' << c << ' ' << d << '\n'; debug(); return 0; } exit(114); } // for (int d = c + 1; d <= 100000; d++) { // int xx = (a ^ b ^ c ^ d); // if (a * a + b * b + c * c + d * d == xx * xx) { // std::cout << d << '\n'; // return 0; // } // std::cerr << a * a + b * b + c * c + d * d << " " << xx * xx << '\n'; // } // std::cout << a << ' ' << b << ' ' << c << ' ' << d << '\n'; // std::cerr << (a ^ b ^ c) << ' ' << a * a + b * b + c * c << '\n'; return 0; }有心路历程的代码,大家可以看看我赛时心态。
- 1
信息
- ID
- 10775
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者