根据需计算的数据量打表,分析各数作用,可有效降低运行时间。
方法一:直接开数组存储
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 5e6;
int a[N],b[N];
bool c[N];
int main(){
int k;
int n;
cin>>n;
for(int i=0;i*i<=n/2;i++){
for(int j=i;i*i+j*j<=n;j++){
k = i*i + j*j;
if(k<5e6 && !c[k]){
a[k] = i;
b[k] = j;
c[k] = true;
}
}
}
for(int i=0;i*i<=n/2;i++){
for(int j=i;i*i+j*j<n/2;j++){
if(c[n-(i*i+j*j)]){
cout<<i<<" "<<j<<" "<<a[n-(i*i+j*j)]<<" "<<b[n-(i*i+j*j)];
return 0;
}
}
}
}
方法二:用unorder_map记录(开启O2/O3优化可过)
#pragma GCC optimize(2)
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
int n, m;
unordered_map<int, PII> S;
int main(){
cin>>n;
for (int c = 0; c * c <= n / 2; c ++ )
for (int d = c; c * c + d * d <= n; d ++ ){
int t = c * c + d * d;
if (S.count(t) == 0) S[t] = {c, d};
}
for (int a = 0; a * a <= n; a ++ )
for (int b = a; a * a + b * b <= n / 2; b ++ ){
int t = n - a * a - b * b;
if (S.count(t)){
printf("%d %d %d %d\n", a, b, S[t].x, S[t].y);
return 0;
}
}
return 0;
}
此时发现超时,弃用unorder_map,直接采用pair数组+状态数组,速度与数组实现一致,远快于采用unorder_map。
方法三:用pair记录
#include <cstring>
#include <iostream>
#include <algorithm>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
int n, m;
const int N = 5e6;
PII S[N];
bool H[N];
int main(){
cin >> n;
for (int a = 0; a * a <= n/2; a ++ )
for (int b = a; a * a + b * b <= n; b ++ ){
int t = a * a + b * b;
if (!H[t]){
S[t] = {a, b};
H[t] = true;
}
}
for (int a = 0; a * a <= n/2; a ++ )
for (int b = 0; a * a + b * b <= n/2; b ++ ){
int t = n - a * a - b * b;
if (H[t]){
printf("%d %d %d %d\n", a, b, S[t].x, S[t].y);
return 0;
}
}
return 0;
}
方法四:用结构体记录,并进行符号重载。sort排序,用二分的方式查找对应值所在的结构体。(开启O2优化可发现优化效果明显)
注意:二分查找时,应采用查找第一个值的二分查找法。
//查找不小于x的第一个位置
int bsearch1(int l, int r){
while(l<r){
int mid = (l+r)>>1;
if(a[mid]<x) l = mid+1;
else r = mid;
}
return l;
}
#pragma GCC optimize(2)
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 2500010;
struct Sum{
int s, c, d;
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 n, m;
int main()
{
cin >> n;
for (int c = 0; c * c <= n; c ++ )
for (int d = c; c * c + d * d <= n; d ++ )
sum[m ++ ] = {c * c + d * d, c, d};
sort(sum, sum + m);
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 = m - 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)
{
printf("%d %d %d %d\n", a, b, sum[l].c, sum[l].d);
return 0;
}
}
return 0;
}