这个题暴力需要至少三层循环,每层大概106严重超时。
优化方法是将四个数分成两拨运算,例如abcd是答案的四个数,先算出a和b,然后temp = n - a - b
再运行循环找出能凑出temp 的c和d,具体寄存方法有二分法和哈希表。
方法一:二分法 (N2logN)
C++描述:
#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;
}
方法二:哈希表 (logN)
Java 描述:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashMap;
public class Main {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter pw = new PrintWriter(System.out);
static int n;
static HashMap<Integer, int[]> map = new HashMap<>();
public static void main(String[] args) throws Exception {
n = Integer.parseInt(br.readLine());
for (int i = 0; i * i <= n; i++)
for (int j = 0; j * j + i * i <= n; j++)
map.put(i * i + j * j, new int[]{i, j});
boolean flag = true;
for (int i = 0; i * i <= n && flag; i++)
for (int j = 0; j * j + i * i <= n && flag; j++) {
int t = n - j * j - i * i;
if (map.containsKey(t)) {
int tmp[] = map.get(t);
int res[] = {tmp[0], tmp[1], i, j};
Arrays.sort(res);
for (int k = 0; k < res.length; k++) pw.print(res[k] + " ");
flag = false;
}
}
pw.flush();
pw.close();
br.close();
}
}