题目
大勾股定理是勾股定理的推广:对任何正整数 n 存在 2n+1 个连续正整数,满足前 n+1 个数的平方和等于后 n 个数的平方和。例如对于 n=1 有 3^2 +4^2 =5^2 ;n=2 有 10^2 +11^2 +12^2 =13^2 +14^2 等。给定 n,本题就请你找出对应的解。
输入格式:
输入在一行中给出正整数 n(≤10^4 )。
输出格式:
分两行输出满足大勾股定理的解,格式如下:
a[0]^2 + a[1]^2 + … + a[n]^2 =
a[n+1]^2 + … + a[2n]^2
其中解的数列 a[0] … a[2n] 按递增序输出。注意行首尾不得有多余空格。
输入样例:
3
输出样例:
21^2 + 22^2 + 23^2 + 24^2 =
25^2 + 26^2 + 27^2
思路
遇到这道有关大勾股数定义的题目,第一反应就是新奇,常规的解题思路在这儿根本行不通。一般人可能会想到用暴力遍历法来试试,就是不管不顾,把所有可能的数挨个尝试一遍,看能不能满足题目要求。但这方法太笨啦,特别浪费时间,而且就算费了好大劲,最后也不一定能得出正确答案。想要找个又快又好的办法,却感觉毫无头绪,脑袋里一团乱麻,真是让人干着急。
不过,那些对数学特别敏感、洞察力强的人就不一样了。他们清楚,任何数学问题背后都藏着规律,只要用心找,肯定能发现。
就拿这道题来说,经过仔细观察和分析,我们发现了一个关键规律:对于任意给定的整数n,恰好有(2n + 1)个数能符合大勾股数相关的等式。既然知道了这个,我们不妨换个思路,试着找找这一堆数里正中间的那个数。
具体来看:当(n = 1)时,中间那个数是4;(n = 2)时,中间数变成12;(n = 3)时,中间数则是24。这几个数乍一看好像没啥联系,可要是把它们拆开分析,就有门道了。(4 = 1×4);(12 = 2×6);(24 = 3×8)。到这儿,是不是感觉有点眉目了?别急,我们再深入研究一下。(1×4)其实就是(1×(2×2));(2×6)就是(2×(2×3));(3×8)实际上是(3×(2×4))。
这下大家肯定都明白了,原来给定一个数n,它对应的大勾股数里,中间那个数的规律就是(n×(2×(n + 1))) 。知道了这个规律,再去写代码解这道题,那就简单多了。再也不用像之前想用暴力计算平方和那样,担心时间不够算不完了。按照这个规律写代码,轻轻松松就能把这道难题解决掉,是不是超厉害!
代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n; // 输入整数 n
vector<int>res; // 定义一个整型向量 res 用于存储结果
int x = n*((n+1)*2)-n; // 计算起始数字
for(int i = 0;i < 2*n+1;i++){ // 循环 2*n + 1 次
res.push_back(x); // 将当前数字 x 存入向量 res
x++; // x 自增 1
}
for(int i = 0;i < n+1;i++){ // 输出等式左边
if(i == 0) printf("%d^2 ",res[i]); // 输出第一个数的平方
else printf("+ %d^2 ",res[i]); // 输出后续数的平方,前面加 + 号
if(i == n) cout<<"="<<endl; // 等式左右两边分隔符
}
for(int i = n+1;i < 2*n+1;i++){ // 输出等式右边
if(i == n+1){ // 输出等式右边第一个数的平方
if(n+1 == 2*n) printf("%d^2",res[i]); // 若只有一个数,不输出空格
else printf("%d^2 ",res[i]);
}
else if(i == 2*n){ // 输出等式右边最后一个数的平方
printf("+ %d^2\n",res[i]);
}
else printf("+ %d^2 ",res[i]); // 输出等式右边中间数的平方
}
return 0;
}