(Violence + Hash Table Optimization) Blue Bridge Cup 2016C\C++A Provincial Competition Zhenti 8Square Sum

topic

The Four Sum of Squares Theorem, also known as Lagrange's Theorem:
  Every positive integer can be expressed as the sum of squares of at most four positive integers.
  If you include 0, 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 ^ symbol means power)

For a given positive integer, there may be multiple representations of the sum of squares.
  You are required to sort 4 numbers:
  0 <= a <= b <= c <= d
  and sort all possible representations in ascending order by a,b,c,d as the joint primary key, and finally output the first representation

The input of the program is a positive integer N (N<5000000), and it is
  required to output 4 non-negative integers, sorted from small to large, separated by spaces

For example, input:
  5
  then the program should output:
  0 0 1 2

For another example, input:
  12
  , the program should output:
  0 2 2 2

For another example, input:
  773535
  , the program should output:
  1 1 267 838

Resource convention:
  peak memory consumption < 256M
  CPU consumption < 3000ms

analyze

When you get an algorithm problem, if there is no better method, think of a violent method first, and the violent method can also get a part of the points, and then in the case of repetition, the violent method of optimizing
this problem is to enumerate a The range of ,b,c,d is the root number n, and the time complexity is about O(n^2). The range of n given in the question is 1e6, so the worst case is about 1e12
. 1. Reducing the
enumeration range
2. Reducing the enumeration variables
1 is not feasible, so we can consider reducing the enumeration variables The
first thing that can be thought of is to omit the enumeration of d, you can use Na ab bc c to represent d, The worst case will probably be reduced to 1e9, and it will also time out.
Then omit c and d, and store na
ab b to represent c c + d d, but at this time we don’t know what c and d are, so this value must be To bind with the value of c or d, we thought of a hash table, using the hash table to bind c c + b b and c, if necessary, directly subtract this value from c c and then square it to get
At this time, we only need to enumerate the last two elements, then store all the combinations in the map, then enumerate a and b, find na ab b in the map , if found, assign c directly, and then calculate d , the answer is found, the loop here should follow the lexicographical order, and the first one found that matches the answer is the answer

full ac code

#include <bits/stdc++.h>
using namespace std;

map<int,int>cache;

int main (void)
{
    
    
	int n;
	cin>>n;
	
	for(int c=0;c*c<=n/2;c++)		//存储后两个数字的平方和 
		for(int d=c;d*d+c*c<=n;d++)
		{
    
    
			if(cache.find(c*c+d*d)==cache.end())
				cache[c*c+d*d]=c;
		} 
		
	for(int a=0;a*a<=n/4;a++)		//循环遍历前两个数字 
		for(int b=a;a*a+b*b<=n/2;b++)
		{
    
    
			if(cache.find(n-a*a-b*b)!=cache.end())
			{
    
    
				int c=cache[n-a*a-b*b];
				int d=sqrt(n-a*a-b*b-c*c);
				printf("%d %d %d %d",a,b,c,d);
				return 0;
			}
		}
		
	return 0;	
}

Summarize

The time complexity of the loop is about O(n) The search time complexity in the map is about O(logn), so the evaluation data here can pass.

Guess you like

Origin blog.csdn.net/weixin_46035615/article/details/123925307