四平方和
四平方和定理,又称为拉格朗日定理:
每个正整数都可以表示为至多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
四平方和定理,又称为拉格朗日定理:
每个正整数都可以表示为至多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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
public class Main{
public static long []temp = new long[4];
public static long []ans = new long[4];
/**
* 存储按照升序排列的第一个答案;逻辑上筛选的规则是:如果ans小于temp中的,表示ans中存储的就是满足条件的,直接return;
* 如果ans大于temp则temp中存储的才是最适合的,则交换。
* 如果相等则进行下一次比较;
* */
public static void saveAns(boolean flag){
//如果是第一个temp直接赋值给ans即可
if(flag) { for(int j = 0; j < temp.length; ++j) ans[j] = temp[j]; }
for(int i = 0; i < 4; ++i) {
if(ans[i] < temp[i]) return;
else if(ans[i] > temp[i]) { for(int j = 0; j < temp.length; ++j) ans[j] = temp[j]; return; }
}
}
/**
* 总的思路是:
* 从这个数num的开根号后得到的数num_sqrt开始遍历:
* 比如:num = 18, i = num_sqrt = 4;
* 4 * 4 = 16,小于18则存储4,num-16后还剩2,故只需从4遍历到0,看那个数的平方不会超过2即可;
* 4 * 4 = 16,大于2,进行下一次
* 3 * 3 = 9,大于2,进行下一次
* 2 * 2 = 4, 大于2,进行下一次
* 1 * 1 = 1,小于2,num - 1 = 1, 此时还要继续判断1是否满足,1 * 1 = 1,小于等于1,num - 1 = 0;
* 此时再调用saveAns()判断该temp中的解是不是需要的解。
*
* 然后i--, i = 3;
* 3 * 3 = 9, 小于18,存储3,num - 9 = 9,继续判断3 * 3 = 9, 9 - 9 = 0,就会跳出while,调用saveAns()方法。
*
* 思路就是从后向前遍历,先看最大的是否满足,不满足就找下一个,满足就存到temp中。
*
* 看不懂我写的文字的话,可以自己在纸上把这个测试用例跑一下!
* 如果那里有错的话,或者改进的地方请大家在留言区留言。THANKS
* */
public static void main(String[] args) throws Exception{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
long num = Long.parseLong(in.readLine());
in.close();
boolean flag = true;
Arrays.fill(ans, 0L);
long renum = 0, num_sqrt = (long)Math.sqrt(num);
for(long i = num_sqrt; i >= 0; --i) {
if(num == i * i) { ans[3] = i; break; }
Arrays.fill(temp, 0L);
renum = num;
int temp_pos = 3;
for(long j = i; temp_pos >=0 && j >= 0; --j) {
while(temp_pos >= 0 && renum !=0 && (renum - j * j) >= 0) {
renum -= j * j;
temp[temp_pos--] = j;
}
if(0 == renum) { saveAns(flag); if(flag) flag = false; break; }
}
}
for(int i = 0; i < ans.length; ++i)
if(i == ans.length - 1) System.out.println(ans[i]);
else System.out.print(ans[i] + " ");
}
}