四平方和定理,又称为拉格朗日定理:
每个正整数都可以表示为至多 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。
输出格式
输出4个非负整数,按从小到大排序,中间用空格分开。
数据范围
0<N<5∗1e6
输入样例:
5
输出样例:
0 0 1 2
#include <bits/stdc++.h>
using namespace std;
int n;
const int N = 2500010;
struct Sum{
int s, c, d;
//排序顺序:先s后c再d,就可以直接sort了
bool operator< (const Sum &t) const{
if(s != t.s) return s < t.s;
if(c != t.c) return c < t.c;
return d < t.d;
}
}sum[N];
int main(){
cin >> n;
int k = 0;
for(int c = 0; c * c <= n; c ++ ){
for(int d = c; c * c + d * d <= n; d ++){//注意这个范围,c * c + d * d <= n
sum[k ++] = {c * c + d * d, c, d};
}
}
sort(sum, sum + k);
for(int a = 0; a * a <= n; a ++){
for(int b = 0; a * a + b * b <= n; b ++){//注意这个从零开始
int t = n - a * a - b * b;
int l = 0, r = k - 1;//注意范围
while(l < r){
int mid = (l + r) >> 1;
if(sum[mid].s >= t) r = mid;
else l = mid + 1;
}
if(sum[l].s == t){
cout << a << ' ' << b << ' ' << sum[l].c << ' ' << sum[l].d << endl;
return 0;
}
}
}
return 0;
}
thought:
#先暴力再优化也是一个好办法
#一般先考虑时间复杂度,然后牺牲空间获得时间,因为空间限制一般不会超
#根据时间复杂度思考枚举几个数
#二分(o(log n))或者哈希(o(1))判断这个数有没有出现过