AcWing 1221. Four square sum (two points, learn y total thinking)

The
meaning of the title: Directly violently use the formula d d=na ab bc c, the time complexity is n^3, timeout.
So use t=na a+b b & sum.y=c c+d d. First find the sum of c and d, and sort the dictionary. Find the first subscript of t=na ab b in the sum[].y arrays in c and d. This is the
key point of the answer :
1. Enumerate at most two numbers, because one number is 2200, three times of 2200 The square has exceeded 100 million
. 2. Use space for time (the key idea of ​​this question)
3. Use dichotomy to find whether a number appears in the previous number
3. How to find the array with the smallest lexicographical order

Your own timeout code is not much different from the total code of y, and the time complexity is O(N^2logN)

#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

const int N = 2500010;

struct Sum//定义结构体 
{
    
    
    int y, e, s;
}sum[N];


int young(Sum a,Sum b){
    
       //结构体排序算法 
    if(a.y > b.y){
    
    
        return 1;
    }
 else if(a.y < b.y){
    
    
        return -1;
    }
 else{
    
    
        if(a.e > b.e){
    
    
            return 1;
        }
  else if(a.e < b.e){
    
    
            return -1;
        }
	 else{
    
    
            if(a.s > b.s){
    
    
                return 1;
            }
   else if(a.s < b.s){
    
    
                return -1;
            }
            else return 0;
        }
    }
}

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 ].y= c * c + d * d;
            sum[m ].e= c;
            sum[m ++ ].s =d; //这样的 m++ 正好可以使 ,最后的m变成数组sum[]的个数 
		}
           
//对结构体进行排序 
    for(int i=0;i<m;i++){
    
    
 		for(int j=i;j<m;j++){
    
    
  			if(young(sum[i],sum[j])>0){
    
    //从小到大排序 
  				 swap(sum[i],sum[j]);
  			}
 		}
 	} 

    for (int a = 0; a * a <= n; a ++ )
        for (int b = a; a * a + b * b <= n; b ++ )
        {
    
    
            int t = n - a * a - b * b;// 此时算出的 t 是最大值,因为t=c*c+d*d。满足题意: a<b<c<d 
            int l = 0, r = m - 1;
            while (l < r)//用于找到下边最小的 t (因为下标最小,则它的后面会满足 c<d ) 
            {
    
    
                int mid = l + r >> 1;
                if (sum[mid].y >= t) r = mid;
                else l = mid + 1;
            }
            if (sum[l].y == t)
            {
    
    
                printf("%d %d %d %d\n", a, b, sum[l].e, sum[l].s);
                return 0;
            }
        }

    return 0;
}

yTotal code, because I participate in the Blue Bridge Cup, so try not to use the std+11 protocol, just learn it by yourself

#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;
}

Guess you like

Origin blog.csdn.net/qq_47874905/article/details/114999348