蓝桥杯第七届省赛第八题-四平方和

四平方和

四平方和定理,又称为拉格朗日定理:
每个正整数都可以表示为至多4个正整数的平方和。
如果把0包括进去,就正好可以表示为4个数的平方和。

比如:
5 = 0^2 + 0^2 + 1^2 + 2^2
7 = 1^2 + 1^2 + 1^2 + 2^2
(^符号表示乘方的意思)

对于一个给定的正整数,可能存在多种平方和的表示法。
要求你对4个数排序:
0 <= a <= b <= c <= d
并对所有的可能表示法按 a,b,c,d 为联合主键升序排列,最后输出第一个表示法

程序输入为一个正整数N (N<5000000)
要求输出4个非负整数,按从小到大排序,中间用空格分开

例如,输入:
5
则程序应该输出:
0 0 1 2

再例如,输入:
12
则程序应该输出:
0 2 2 2

再例如,输入:
773535
则程序应该输出:
1 1 267 838

在看到这个题目是,我感觉并没有什么好的方法可以解决这个该问题,于是使用了暴力的方式,在优化了循环之后也能AC大部分例子,但是在做这个题的过程中却遇到了问题比如循环变量未优化造成K值过大k值的平方溢出了int型变量的取值范围,然后有在奇妙的操作下满足了if条件,造成了数据773535及之后的数据结果都出现了错误不能AC,也有了很多收获,于是想要记下来,让自己下次养成好习惯避免这种错误,同时节约计算机的时间和空间消耗!错误及心得均在代码注释里。
代码

//773535,这个测试用例在1(自写) 2(借鉴)两个demo中运行表现出了截然不同的运行效果,而借鉴的优化之处在于避免了很多不必要的循环次数,所以在编程当中
//一定不要轻视循环变量的作用,一定要在可能的情况下,尽量减小循环的开销!!! 而且自己写的demo在运行到773535以及之后时,由于未优化循环变量,造成K的平方值
//过于巨大,溢出了int型的取值范围,然后在奇妙的操作下造成了773535之后的结果全部错误 不能AC,虽然可以用ll来解决一定的问题,但是最根本的还是
//养成对程序中的各种变量尽可能优化的习惯,以减少可避免的错误,和节约时间以及空间!! 
/*#include<iostream>
#include<cmath>
using namespace std;
int main(){
	int num;
	cin>>num;
	for(int i=0;i<num;i++){		
		for(int j=i;j<num;j++){		
			for(int k=j;k<num;k++){
			 if(int(pow(int(pow(num-i*i-j*j-k*k, 0.5)), 2)) == (num-i*i-j*j-k*k)) {
			 		cout<<k*k<<endl;
			 		cout<<k<<endl;
			 		cout<<(int(pow(int(pow(num-i*i-j*j-k*k, 0.5)), 2)))<<endl;
                    cout << i << ' ' << j << ' ' << k << ' ' << pow(num-i*i-j*j-k*k, 0.5);
                    return 0;
                }
				
			}
		}
	} 
	cout<<"无效数据!"<<endl; 
}*/

#include <iostream>
#include <cmath>
using namespace std;

int main()
{
    int n;
    cin >> n;
    for(int i = 0; i*i < n; ++i) {
        for(int j = i; j*j + i*i < n; ++j) {
            for(int k = j; k*k + j*j + i*i < n; ++k) {//每一个循环变量的取值均以上一个为基础,在一遇到满足条件就输出的情况下,就能输出升序排列的第一个 
                if(int(pow(int(pow(n-i*i-j*j-k*k, 0.5)), 2)) == (n-i*i-j*j-k*k)) {
                    cout << i << ' ' << j << ' ' << k << ' ' << pow(n-i*i-j*j-k*k, 0.5);
                    return 0;
                }
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值