题目
四平方和定理,又称为拉格朗日定理:
每个正整数都可以表示为至多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).
输出描述
输出四个非负整数,按从小到大排序,中间用空格隔开。
示例:
输入
12
输出
0 2 2 2
运行限制
1、最大运行时间:3s
2、最大运行内存:256M
解题思路
本题需要将一个整数拆为四个非负数的平方和,由于它的数值较小,直接采用暴力枚举的方法就可以。需要注意的是输出条件:对所有的可能表示法按 a,b,c,d 为联合主键升序排列,最后输出第一个表示法。
举个例子:
输入为18时,可得到a.b.c.d的所有可能为:
0 1 1 4
1 2 2 3
0 0 3 3
将 a,b,c,d 联合主键升序排列,为:
0 0 3 3
0 1 1 4
1 2 2 3
此时应该输出第一个表达式,即0 0 3 3
代码
#include <iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int a,b,c,d;//保存a、b、c、d的数据
int main()
{
int n;//输入
int m1, m2, m3, m4;//保存每选定一个数(a或b或c或d)后,剩余的差
cin >> n;
for (; a <= sqrt(n); a++)//a[0]为全局变量,初始化为0
{//sqrt函数为求根函数
m1 = n - a * a;
for (b = 0; b <= sqrt(m1); b++)//每次第一个循环都要将a[1]赋值为0
{
m2 = m1 - b * b;
for (c = 0; c <= sqrt(m2); c++)//每次第二个循环都要将a[2]赋值为0
{
m3 = m2 - c * c;
d = sqrt(m3);//a、b、c确定后,d为定值,故不用枚举
m4 = m3 - d * d;//由于int类型限制,若m3==3,d==1,m3==4,d==2;
if (m4 == 0)
break;
}
if (m4 == 0)
break;
}
if (m4 == 0)
break;
}//由于a和b和c都是从0开始循环,那么得出来的数一定为a<=b<=c<=d,且d一定为正整数,故用m4判断循环的截止;
cout << a << " " << b << " " << c << " " << d;
return 0;
}
结果
20
0 0 2 4
9
0 0 0 3
599999
1 3 342 695
执行最慢用时:82ms
内存:1672kb