四平方和定理问题

题目描述

四平方和定理,又称为拉格朗日定理:

每个正整数都可以表示为至多 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);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值