四平方和
四平方和定理,又称为拉格朗日定理:
每个正整数都可以表示为至多4个正整数的平方和。
如果把0包括进去,就正好可以表示为4个数的平方和。
比如:
5 = 0^2 + 0^2 + 1^2 + 2^2
7 = 1^2 + 1^2 + 1^2 + 2^2
(^符号表示乘方的意思)
对于一个给定的正整数,可能存在多种平方和的表示法。
要求你对4个数排序:
0 <= a <= b <= c <= d
并对所有的可能表示法按 a,b,c,d 为联合主键升序排列,最后输出第一个表示法
程序输入为一个正整数N (N<5000000)
要求输出4个非负整数,按从小到大排序,中间用空格分开
例如,输入:
5
则程序应该输出:
0 0 1 2
再例如,输入:
12
则程序应该输出:
0 2 2 2
再例如,输入:
773535
则程序应该输出:
1 1 267 838
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 3000ms
这题比较坑,关键是不能着急退出,要搜索全部情况,但加点优化时间也不是很长.
首先我们在sqrt(N)的时间生成一个数组a,里面存平方数
然后再 sqrt(N)^2时间内生成一个数组b,里面存平方数 * 平方数
关键是利用一个长度为N的数组C
C是一个结构体数组
.b表示这个C[i]是否是 平方数 * 平方数,也就是形如x^2 +y^2的形式
同时 .x .y记录x和y
一切准备就绪之后
就枚举b数组
然后根据c数组直接得到是否满足
注意不要找到第一组就退出循环,而是要把每种情况都找出来再比较
实际上也只是需要sqrt(N)^2的时间
这里用一个pair<pair<int, int>, pair<int, int> >类型来方便比较
#include <bits/stdc++.h>
using namespace std;
const int INF = INT_MAX;
struct V
{
bool b;
int x, y;
V()
{
b = false;
x = 0;
y = 0;
}
V(bool b, int x, int y) : b(b), x(x), y(y) {}
};
auto makePair(int a, int b, int c, int d)
{
return make_pair(make_pair(a, b), make_pair(c, d));
}
int main()
{
int n;
scanf("%d", &n);
vector<int> a;
for (int i = 0; i * i <= n; i++) a.push_back(i * i);
vector<int> b;
vector<V> c;
c.resize(n + 1);
for (int i = 0; i < a.size(); i++) {
for (int j = i; j < a.size(); j++) {
if (a[i] + a[j] > n) continue;
if (c[a[i] + a[j]].b) {
if (sqrt(a[i]) < c[a[i] + a[j]].x) c[a[i] + a[j]] = V(true, sqrt(a[i]), sqrt(a[j]));
} else {
b.push_back(a[i] + a[j]);
c[a[i] + a[j]] = V(true, sqrt(a[i]), sqrt(a[j]));
}
}
}
auto ans = makePair(INF, INF, INF, INF);
for (int e : b) {
if (n - e >= 0 && c[n - e].b) {
//printf("%d %d %d %d\n", c[e].x, c[e].y, c[n-e].x, c[n-e].y);
ans = min(ans, makePair(c[e].x, c[e].y, c[n-e].x, c[n-e].y));
}
}
cout << ans.first.first << ' ' << ans.first.second << ' ' << ans.second.first << ' ' << ans.second.second << endl;
}