题目描述
四平方和定理,又称为拉格朗日定理:
每个正整数都可以表示为至多 44 个正整数的平方和。
如果把 00 包括进去,就正好可以表示为 44 个数的平方和。
比如:
5=02+02+12+225=02+02+12+22。
7=12+12+12+227=12+12+12+22。
对于一个给定的正整数,可能存在多种平方和的表示法。
要求你对 44 个数排序使得 0≤a≤b≤c≤d。
并对所有的可能表示法按 a,b,c,d 为联合主键升序排列,最后输出第一个表示法。
输入格式
程序输入为一个正整数 N(N<5×106)。
输出格式
要求输出 44 个非负整数,按从小到大排序,中间用空格分开。
package 练习;
import java.util.*;
import java.lang.*;
public class 暴力算法 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int x = (int) Math.sqrt(n);
for(int j = 0 ; j < x ; j ++) {
int y = (int) Math.sqrt(n - j * j);
for(int k = j ; k < y ; k++ ) {
int a = (int) Math.sqrt(n - j * j - k * k);
for(int l = k ; l < a ;l ++ ) {
int b = (int) Math.sqrt(n - j * j - k * k - l * l);
for(int m = l ; m < b ;m ++ ) {
if(j * j + k * k + l * l + m * m == n)
if(j <= k && k <= l && l <= m)
System.out.println(j + " " + k + " " + " " + l + " " + m);
}
}
}
}
scan.close();
}
}
这段代码没有结果。
为什么呢,应该是太复杂了,时间复杂度果然太大了
package 练习;
import java.util.*;
import java.lang.*;
public class 暴力算法 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int x = (int) Math.sqrt(n);
for(int j = 0 ; j < x ; j ++) {
for(int k = j ; k * k + j * j < n ; k++ ) {
int remaining = n - j * j - k * k;
for(int l = k ; l * l+ j * j + k * k < n ;l ++ ) {
int m = (int) Math.sqrt(remaining - l * l);
if (m * m == remaining - l * l && m > 0 && l <= m) { // 验证m是整数,并且满足顺序条件
System.out.println(j + " " + k + " " + l + " " + m);
}
}
}
scan.close();
}
}
}
这样就行了。
但是我们不应该止步于此
package 练习;
import java.util.*;
import java.lang.*;
public class 暴力算法 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int x = (int) Math.sqrt(n);
for(int j = 0 ; j < x ; j ++) {
int z = (int) Math.sqrt(n - j * j);
for(int k = 0 ; k * k + j * j < n ; k++ ) {
int y = (int) Math.sqrt(n - j * j - k * k);
for(int l = 0 ; l < y ;l ++ ) {
if (j * j + k * k + l * l == n) {// 验证m是整数,并且满足顺序条件
System.out.println(j + " " + k + " " + l );
}
}
}
scan.close();
}
}
}
这个代码把为题缩小成了n = i * i + j * j + k * k;直接少了一个for循环还是没反应。
package 练习;
import java.util.*;
import java.lang.*;
public class 暴力算法 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int x = (int) Math.sqrt(n);
for(int j = 0 ; j < x ; j ++) {
int z = (int) Math.sqrt(n - j * j);
for(int k = 0 ; k < z ; k++ ) {
if (j * j + k * k == n) {// 验证m是整数,并且满足顺序条件
System.out.println(j + " " + k );
}
}
scan.close();
}
}
}
继续化简还是没有用。
AI告诉我
在内层循环中,变量
z
计算了Math.sqrt(n - j * j)
,而k
的循环条件是k < z
,这可能导致在某些情况下错过解是的k <= z才是正解
,因为在循环条件中允许k
直接到达z
,但实际上我们需要k * k <= n - j * j
才能得到正确的解。
我一试,就成了
对于输入的
n = 5
,这段代码确实应该能够找到解,也就是(j, k) = (2, 1)
,因为2^2 + 1^2 = 5
。然而,没有输出的原因可能在于,代码中计算
z
的方式:Java
1int z = (int) Math.sqrt(n - j * j);
在
j = 2
时,z
的值将会是1
,然后内层循环只会循环一次,对应k = 0
,这时j * j + k * k = 4 + 0 ≠ 5
,因此没有打印结果。为了找到正确的解,应确保内层循环能够覆盖到所有可能的
k
值,即当k
的平方不超过n - j * j
时。正确的内层循环条件应改为:Java
1for(int k = 0 ; k * k <= n - j * j ; k++ ) {
这样,当
j = 2
时,k
将会遍历到1
,从而找到并输出(2, 1)
这个解。如果修改了循环条件后依然没有输出结果,请检查其它可能影响代码执行的因素,如是否正确读取了输入值,或是否有其他的逻辑错误。
package 练习; import java.util.*; import java.lang.*; public class 暴力算法 { public static void main(String[] args) { Scanner scan = new Scanner(System.in); int n = scan.nextInt(); int x = (int) Math.sqrt(n); for(int j = 0 ; j < x ; j ++) { int z = (int) Math.sqrt(n - j * j); for(int k = 0 ; k <= z ; k++ ) { if (j * j + k * k == n) {// 验证m是整数,并且满足顺序条件 System.out.println(j + " " + k ); } } } } }
这下对了
package 练习;
import java.util.*;
import java.lang.*;
public class 暴力算法 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int x = (int) Math.sqrt(n);
for(int j = 0 ; j <= x ; j ++) {
int y = (int) Math.sqrt(n - j * j);
for(int k = j ; k <= y ; k++ ) {
int a = (int) Math.sqrt(n - j * j - k * k);
for(int l = k ; l <= a ;l ++ ) {
int b = (int) Math.sqrt(n - j * j - k * k - l * l);
for(int m = l ; m <= b ;m ++ ) {
if(j * j + k * k + l * l + m * m == n)
if(j <= k && k <= l && l <= m)
System.out.println(j + " " + k + " " + " " + l + " " + m);
}
}
}
}
scan.close();
}
}
现在原来最开始不行的也可以了
package 练习;
import java.util.*;
import java.lang.*;
public class 暴力算法 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int x = (int) Math.sqrt(n);
for(int j = 0 ; j <= x ; j ++) {
for(int k = 0 ; j * j + k * k <= n ; k++ ) {
for(int l = 0 ; j * j + k * k + l * l<= n ;l ++ ) {
double m = Math.sqrt(n - j * j - k * k - l * l);
boolean isInt = (m == (int)m);
if(isInt) {
if(j * j + k * k + l * l + m * m == n) {
int a = (int) m ;
System.out.println(j + " " + k + " " + l + " " + a);
System.exit(0);
}
}
}
}
}
scan.close();
}
}
上面,这个代码最终通过了测试。下面这个由于粗心没有加if(j * j + k * k + l * l + m * m == n) 所以错了
import java.util.*;
import java.lang.*;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int x = (int) Math.sqrt(n);
int b = 0;
for(int j = 0 ; j <= x ; j ++) {
for(int k = 0 ; j * j <= n ; k++ ) {
for(int l = 0 ; j * j + k * k <= n ;l ++ ) {
double m = Math.sqrt(n - j * j - k * k - l * l);
boolean isInt = (m == (int)m);
if(isInt) {
b = (int)m;
System.out.println(j + " " + k + " " + " " + l + " " + b);
System.exit(0);
}
}
}
}
scan.close();
}
}
破案了
System.out.println(j + " " + k + " " + " " + l + " " + m);
---------------------------------------------------------------------------------------------------------------------------------
之前大部分通过不了是因为这个原因。
1.在内层循环中,变量
z
计算了Math.sqrt(n - j * j)
,而k
的循环条件是k < z
,这可能导致在某些情况下错过解是的k <= z才是正解
,因为在循环条件中允许k
直接到达z
,但实际上我们需要k * k <= n - j * j
才能得到正确的解。2.
System.out.println(j + " " + k + " " + " " + l + " " + m);