Problem describe
The Four Squares Theorem, also known as Lagrange's Theorem:
Every positive integer can be expressed as the sum of the squares of at most 4 positive integers.
If 0 is included, it can be expressed as the sum of the squares of 4 numbers.
For example:
5 = 0^2 + 0^2 + 1^2 + 2^2
7 = 1^2 + 1^2 + 1^2 + 2^2
(The ^ sign means power)
for a given For positive integers, there may be multiple representations of the sum of squares.
You are required to sort the 4 numbers:
0 <= a <= b <= c <= d
and arrange all possible representations in ascending order by a, b, c, d as the joint primary key, and finally output the first representation
program input is a positive integer N (N <5000000)
claim outputs 4 non-negative integer, in ascending order, the intermediate separated by a space
, for example, input:
. 5
, the program should output:
0,012
another example, input:
12 is
then the The program should output:
0 2 2 2
For another example, input:
773535
, the program should output:
1 1 267 838
Thought process
Meaning of the title: literal meaning, note: the ascending order of the combined primary key can be understood as lexicographical order (comparison letter by letter). Such as: 01234>1.
Inferior solution: The
first thing that comes to mind is the four-fold for loop enumeration, and the time complexity is estimated: the most extreme case is: when n=500w, a, b, c, d are equal respectively (assuming they can be equal), which is 1118, then the scale is about 1 trillion. Normally, it runs about 10 million times per second, so it is absolutely not feasible (of course, it can also get some steps)
Moderate solution:
Next consider:
1. If a, b, and c are known, d can be derived from the equation: d=n-a*a-b*b-c*c
so it can be reduced to a triple cycle , and the scale is reduced to 100 million;
2. Because the problem is given by the rule: press the joint primary key Sorting in ascending order, therefore, satisfies the equation, a<=b<=c<=d . When enumerating, adding this restriction condition will roughly double the problem size (see Gauss theorem for proof). In this way, all the samples can be passed.
Superior solution:
Of course, the more optimized solution is hash mapping .
Through the map container, it will c*c+d*d
do the mapping, and then double loop traversal a*a和b*b
. If n-a*a-b*b
there is a mapping, it means that there are reasonable a, b, c, d. Just output.
Two codes are given next.
Brute force optimization_code
#include<bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
int n=773535;
int len = sqrt(n);
for(int i = 0 ; i <= len; i++)
for(int j = i; j <= len; j++)
for(int k = j; k <= len; k++) {
int l = n - i*i - j*j - k*k;
if(i*i + j*j + k*k + l*l == n) {
int a[4]; a[0]=i; a[1]=j; a[2]=k; a[3]=l;
sort(a, a+4);
cout << a[0] << ' ' << a[1] << ' ' << a[2] << ' ' << a[3] << endl;
return 0;
}
}
return 0; }
hash_code
#include<bits/stdc++.h>
using namespace std;
int N;
int main() {
ios::sync_with_stdio(false);
int a, b, c, d;
map<int, int>cache;
cin>>N;
int len = sqrt(N);
for(c=0; c*c<=N/2; c++)
for(d=0; c*c+d*d<=N; d++)
cache[c*c + d*d]=c; //映射平方和
for(a=0; a*a<=N/4; a++)
for(b=0; a*a+b*b<=N/2; b++)
if(cache.find(N-a*a-b*b) != cache.end()) {
//找不到则返回cache.end()
c = cache[N-a*a-b*b];
d = (int)(sqrt(N-a*a-b*b-c*c));
cout << a << ' ' << b << ' ' << c << ' ' << d <<'\n';
return 0;
}
return 0; }