题目

一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?


思路

设这个整数为 x x x;

  • 加上100是完全平方数: x + 100 = m 2 x + 100 = m^2 x+100=m2;
  • 再加上168又是完全平方数: x + 100 + 168 = n 2 x + 100 + 168 = n^2 x+100+168=n2;
  • 两式合并: n 2 − m 2 = 168 n^2 - m^2 = 168 n2−m2=168;
  • 解方程: n 2 − m 2 = ( n + m ) ( n − m ) = 168 n^2 - m^2 = (n+m)(n-m) = 168 n2−m2=(n+m)(n−m)=168;
  • 设置 i , j i,j i,j: i = n + m , j = n − m i = n+m, j = n-m i=n+m,j=n−m; 则 i ∗ j = 168 i*j = 168 i∗j=168;
  • 代入可得: n = ( i + j ) / 2 , m = ( i − j ) / 2 n = (i+j)/2, m = (i-j)/2 n=(i+j)/2,m=(i−j)/2;

  • 由 n , m n,m n,m都是整数可知: i , j i,j i,j 都是整数;
  • 由 n , m n,m n,m都是正数(完全平方根)且 m < n m<n m<n 可知: i > j > 0 i>j>0 i>j>0;

  • 关于 i , j i,j i,j的奇偶性:
    • i + j = ( n + m ) + ( n − m ) = 2 n i+j = (n+m)+(n-m) = 2n i+j=(n+m)+(n−m)=2n => 偶数
    • i − j = ( n + m ) − ( n − m ) = 2 m i-j = (n+m)-(n-m) = 2m i−j=(n+m)−(n−m)=2m => 偶数
    • 可得: i , j i,j i,j同奇同偶;
    • 根据 i ∗ j = 168 i*j=168 i∗j=168 可知: i , j i,j i,j同为偶数;

  • 确定范围:
    • 由 (1) i ∗ j = 168 i*j=168 i∗j=168, (2) i , j i,j i,j同为偶数, (3) i > j > 0 i>j>0 i>j>0 可知: j > = 2 j>=2 j>=2, 且 i = 168 / j < = 168 / 2 = 84 i = 168/j <= 168/2=84 i=168/j<=168/2=84;
    • 故范围为: 2 < = i < = 84 , j > = 2 2 <= i <= 84, j >= 2 2<=i<=84,j>=2;

  • 由 i , j i,j i,j 的值往回退找到 x x x:
    • 由 n = ( i + j ) / 2 , m = ( i − j ) / 2 n=(i+j)/2, m=(i-j)/2 n=(i+j)/2,m=(i−j)/2, 可知 x = m 2 − 100 x=m^2-100 x=m2−100;

代码

#include <stdio.h>

int main(){
    int x;
    int m, n;
    int i, j;
    int count=0;

    for(i=2; i<=84; i=i+2){ // i是从2开始的偶数
        if(168%i == 0){ // i能够被168整除(根据i*j=168)
            j = 168/i;
            if(j>=2 && i>j && (i+j)%2==0){
                // 计算m,n
                m = (i-j) / 2;
                n = (i+j) / 2;
                //计算x
                x = m*m - 100;
                count++;
                printf("第%d个数是:%d \n", count, x);
                printf("%d + 100 = %d * %d \n", x, m, m);
                printf("%d + 100 + 168 = %d * %d \n", x, n, n);
                printf("\n");
            }
        }
    }

    return 0;
}

输出结果

第1个数是:-99 
-99 + 100 = 1 * 1 
-99 + 100 + 168 = 13 * 13 

第2个数是:21 
21 + 100 = 11 * 11 
21 + 100 + 168 = 17 * 17 

第3个数是:261 
261 + 100 = 19 * 19 
261 + 100 + 168 = 23 * 23 

第4个数是:1581 
1581 + 100 = 41 * 41 
1581 + 100 + 168 = 43 * 43 




# 一个暴力遍历x的方法

思路

  • 设这个数是x;

  • 在x的取值范围中遍历,判断每一个x是不是符合条件;

  • 难点是要确定x的范围;

  • 由题可知: x + 100 = m 2 , x + 100 + 168 = n 2 x + 100 = m^2, x + 100 + 168 = n^2 x+100=m2,x+100+168=n2;

  • 由 x + 100 = m 2 x + 100 = m^2 x+100=m2 可知: x > = − 100 x>=-100 x>=−100;

  • n 2 − m 2 = 168 n^2 - m^2 =168 n2−m2=168, 当m增大时,n也增大,n和m越来越接近;

  • 找出最大的m:

    • 设 n = m + 1; (这是n比m大的最小整数差)
    • 那么 ( m + 1 ) 2 − m 2 = 168 (m+1)^2 - m^2 = 168 (m+1)2−m2=168;
    • 计算得:m = 83.5;
    • 所以在 m>83 的时候,不管 n 取多少,都不能满足 n 2 − m 2 = 168 n^2-m^2=168 n2−m2=168;
      • 解释:当 m=84 时,n=85, n 2 − m 2 = 169 n^2-m^2=169 n2−m2=169,大于168;
      • 所以,其他的 n 的取值都不会再满足 n 2 − m 2 = 168 n^2-m^2=168 n2−m2=168;
    • 最终取得最大的 m 为 83;

  • 根据最大的 m,可以找到 x 的上界:

    • 当 $m=84 时, x = 84 ∗ 84 − 100 = 6956 x = 84*84 - 100 = 6956 x=84∗84−100=6956;

  • 最终得到x的范围是[-100, 6956];

代码

#include <stdio.h>
#include <math.h> // 包含头文件math.h,里面有sqrt()函数

int main(){
    int x;
    int count = 0;

    for(x=-100; x<=6956; x++){
        int m = sqrt(x + 100); // 计算x + 100的平方根m
        int n = sqrt(x + 100 + 168); // 计算x + 100 + 168的平方根n
        // sqrt()函数返回一个double型的平方根;
        // 在这里强制转换为int类型,出现截断取整;
        // 只有正好是整数的平方根没有变化,在后面的判断中可以返回计算出正确的数值;

        // 检查判断是否是完全平方
        if(m*m == x + 100 && n*n == x + 100 + 168){
            count++;
            printf("第%d个数是:%d \n", count, x);
            printf("%d + 100 = %d * %d \n", x, m, m);
            printf("%d + 100 + 168 = %d * %d \n", x, n, n);
            printf("\n");
        }
    }

    return 0;
}




# 一个遍历m的方法(遍历效率高一点)

思路

  • 设这个数是x;

  • 设 x + 100 = m 2 , x + 100 + 168 = n 2 x + 100 = m^2, x + 100 + 168 = n^2 x+100=m2,x+100+168=n2;

  • 因为是完全平方数,所以必须满足 n>m>0;

  • 找出最大的m:

    • 设n = m + 1; (这是n比m大的最小整数差)
    • 那么 ( m + 1 ) 2 − m 2 = 168 (m+1)^2 - m^2 = 168 (m+1)2−m2=168;
    • 计算得:m = 83.5;
    • 所以在 m>83 的时候,不管n取多少,都不能满足 n 2 − m 2 = 168 n^2-m^2=168 n2−m2=168;
      • 解释:当 m = 84 m=84 m=84 时, n = 85 , n 2 − m 2 = 169 n=85,n^2-m^2=169 n=85,n2−m2=169,大于168;
      • 所以,其他的n的取值都不会再满足 n 2 − m 2 = 168 n^2-m^2=168 n2−m2=168;
  • 最终取得最大的m为83;

  • 故m的取值范围是[0,83];

  • 通过遍历m,然后计算n并取平方根作比较来判断x是否满足条件;

代码

#include <stdio.h>
#include <math.h>

int main(){
    int x;
    int m, n;
    int count = 0;

    for(m=0; m<84; m++){
        int temp = m*m + 168; // n^2 = m^2 + 168
        int n = sqrt(m*m + 168); // 计算n的平方根
        
        if(n*n == temp){ // 判断是否为完全平方
            count++;
            x = m*m - 100;
            printf("第%d个数是:%d \n", count, x);
            printf("%d + 100 = %d * %d \n", x, m, m);
            printf("%d + 100 + 168 = %d * %d \n", x, n, n);
            printf("\n");
        }
    }

    return 0;
}

更多推荐