前言:
在结构体中重写大于小于号是一种很实用的技巧,重写">","<"后再使用c++自带的sort()排序可以解决大部分对输出有特殊要求的题目,当然也可以不进行重写,对sort()函数第三个参数(排序规则)进行编辑也可达到此目的,下面是原题和两种方式的写法:
题目:
四平方和定理,又称为拉格朗日定理:
每个正整数都可以表示为至多4个正整数的平方和。
如果把0包括进去,就正好可以表示为4个数的平方和。
比如:
5=02+02+12+22
7=12+12+12+22
对于一个给定的正整数,可能存在多种平方和的表示法。
要求你对4个数排序:
0≤a≤b≤c≤d
并对所有的可能表示法按 a,b,c,d为联合主键升序排列,最后输出第一个表示法。
(注意加粗部分的描述,对数据输出有特殊要求,意思就是按a < b < c < d的字典序输出)
输入格式
输入一个正整数 N。
输出格式
输出4个非负整数,按从小到大排序,中间用空格分开。
数据范围
0<N<5∗10^6
输入样例:
5
输出样例:
0 0 1 2
首先介绍重写“>”,"<"方法:
struct num{
int a,b,c;
bool operator <(const num &p) const{//重载“<”号 ,比较运算符需要两个数据进行比较,如x < y,在这里函数中的p是传入的参数,也就是后者y
if(a != p.a){//第一关键字
return a < p.a;//第一关键字不同则比较第一关键字
}
else if(b != p.b){//第二关键字
return b < p.b;//第二关键字不同则比较第二关键字
}
else{
return c < p.c;//第三关键字
}
//可以继续添加第四第五等....
}
};
num data[100];
sort(data, data + count);//后续输入数据后直接调用sort即可
再来看自定义sort()排序函数方法:
struct num{
int a, b, c;
};
num data[100];
bool check(num x,num y){//自定义排序规则函数,注意返回值类型必须是bool类型
if(x.a != y.a){
return x.a < y.a;
}
else if(x.b != y.b){
return x.b < y.b;
}
else{
return x.c < y.c;
}
}
sort(data, data + count, check);//注意第三个参数传入排序函数
最后是题解:
这里用的二分查找的纯暴力做法+结构体排序,思路是先暴力枚举c和d的所有情况建立字典,再对a和b进行暴力,枚举时直接使用二分查找之前建立字典的方法(空间换时间)优化掉对c和d的暴力枚举,这里时间复杂度为O(n^2logn)可以通过所有测试集,这边只示范了自定义sort()排序方法的代码,重写">"或"<"的代码可以自行修改:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
struct num{
int sum, c, d;
};
bool check(num x, num y){
if(x.sum != y.sum){
return x.sum < y.sum;
}
else if(x.c != y.c){
return x.c < y.c;
}
else{
return x.d < y.d;
}
}
const int N = 2500010;//根据组合类型枚举大致求出,枚举c与d并存入num进行排序时c至多有(√n * √n)/2种可能
num record[N];
int n;
int main(){
scanf("%d", &n);
int count = 0;
for(int c = 0; c * c <= n; c++){
for(int d = c ;c * c + d * d <= n; d++){
record[count++] = {c * c + d * d, c, d};
}
}
sort(record, record + count, check);
for(int a = 0; a * a <= n; a++){
for(int b = a; b * b + a * a <= n; b++){
int target = n - b * b - a * a;
int l = 0, r = count;
while(l < r){
int mid = (l + r) / 2;
if(record[mid].sum < target){
l = mid + 1;
}
else{
r = mid;
}
}
if(record[r].sum == target){
printf("%d %d %d %d", a, b, record[r].c, record[r].d);
return 0;
}
}
}
return 0;
}