【问题描述】
四平方和定理,又称为拉格朗日定理:
每个正整数都可以表示为至多 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。
【输出格式】
输出4个非负整数,按从小到大排序,中间用空格分开。
【数据范围】
0 < N < 5∗10^6
【输入样例】
5
【输出样例】
0 0 1 2
题解1
暴力做法: 大概能拿到80%的分数
#include <cstdio>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
for (int a = 0; a*a <= n; a ++)
for (int b = a; a*a + b*b <= n; b ++)
for (int c = b; a*a + b*b + c*c <= n; c ++)
for (int d = c; a*a + b*b + c*c + d*d <= n; d ++)
if(a*a + b*b + c*c + d*d == n)
{
printf("%d %d %d %d", a, b, c, d);
return 0;
}
}
题解2
稍加优化: 虽然是三重循环,但是依然能拿到100%的分数,以5000000为例,它的四平方和分别为 0 0 232 2224,可见循环次数非常少
#include <cstdio>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
int main()
{
int n;
cin >> n;
for (int a = 0; a*a <= n; a ++)
for (int b = a; a*a + b*b <= n; b ++)
for (int c = b; a*a + b*b + c*c <= n; c ++)
{
int t = n - a*a - b*b - c*c;
int d = sqrt(t);
if(d*d == t && d >= c)
{
printf("%d %d %d %d", a, b, c, d);
return 0;
}
}
}