题目
四平方和定理,又称为拉格朗日定理:
每个正整数都可以表示为至多 4 个正整数的平方和。
如果把 0 包括进去,就正好可以表示为 4 个数的平方和。
比如:
5=02+02+12+22
7=12+12+12+22
对于一个给定的正整数,可能存在多种平方和的表示法。
要求你对 4 个数排序:
0≤a≤b≤c≤d
并对所有的可能表示法按 a,b,c,d 为联合主键升序排列,最后输出第一个表示法。
输入格式
输入一个正整数 N。
输出格式
输出4个非负整数,按从小到大排序,中间用空格分开。
数据范围
0<N<5∗106
输入样例:
5
输出样例:
0 0 1 2
解题思路:本题首先想到的思路思路是暴力,四层循环但是很显然会超时,我们对他进行优化,其实最后一层循环没有必要,我们可以更具前三个算出最后一个数的值,但是三层循环,每层循环的复杂度达1e3任然会超时,其实本题只需要两层循环,我们先求出两层循环在N的范围内能表示的平方值,值取小的那个,如果a[N-ii-jj]的值不为初始值-1则表示有解。
代码:
显示4层循环
#include<cstdio>
#include<math.h>
int a[5000010];
int main(void){
int N;
scanf("%d",&N);
for(int i = 0;i<= sqrt(N);i++){
for(int j = i;j <= sqrt(N);j++){
for(int m = j;m <= sqrt(N);m++){
for(int n = m;n <= sqrt(N);n++)
if(i*i+j*j+m*m+n*n == N){
printf("%d %d %d %d",i,j,m,n);
return 0;
}else if(i*i+j*j+m*m+n*n > N)
break;
}
}
}
}
//三层循环
#include<cstdio>
#include<math.h>
int a[5000010];
int main(void){
int N;
scanf("%d",&N);
for(int i = 0;i <= sqrt(N);i++){
for(int j = i;j <= sqrt(N);j++){
for(int m = j;m <= sqrt(N);m++){
int n = sqrt(N-i*i-j*j-m*m);
if(i*i+j*j+m*m+n*n == N){
printf("%d %d %d %d",i,j,m,n);
return 0;
}
}
}
}
}
//两层循环
#include<cstdio>
#include<string.h>
#include<math.h>
int a[5000010];
int main(void){
memset(a,-1,sizeof(a));
int N;
scanf("%d",&N);
for(int i = 0;i*i <= N;i++){
for(int j = i;i*i+j*j <= N;j++){
if(a[i*i+j*j] == -1) //这里一定要有这一步,即如果更新后不能再被更新,否则输出的不是按照字典序最小的。
a[i*i+j*j] = i;
}
}
for(int i = 0;i*i <= N;i++){
for(int j = i;i*i+j*j <= N;j++){
if(a[N-i*i-j*j]!=-1){
int c = a[N-i*i-j*j];
int d = (int)sqrt(N-i*i-j*j-c*c);
printf("%d %d %d %d",i,j,c,d);
return 0;
}
}
}
return 0;
}