蓝桥杯 第七届蓝桥杯省赛C++A/B组 四平方和

四平方和定理,又称为拉格朗日定理:

每个正整数都可以表示为至多 4 个正整数的平方和。

如果把 0 包括进去,就正好可以表示为 4 个数的平方和。

比如:

5=0^2+0^2+1^2+2^2
7=1^2+1^2+1^2+2^2

对于一个给定的正整数,可能存在多种平方和的表示法。

要求你对 44 个数排序:

0≤a≤b≤c≤d

并对所有的可能表示法按 a,b,c,d 为联合主键升序排列,最后输出第一个表示法。

输入格式

输入一个正整数 N。

输出格式

输出4个非负整数,按从小到大排序,中间用空格分开。

数据范围

0<N<5∗10^6

输入样例:

5

输出样例:

0 0 1 2
0<N<5∗10^6,因此a,b,c,d的最大取值约为5000,而暴力三层循环时间复杂度会达到10^9,虽然这道题的三次循环也可以过,,,

更好的算法思路是: 用空间换时间,将3层循环换成两次的两层循环这样在时间复杂度上就是可以接受的了。

先一个二层循环将c^2 +  d^2 存起来。 然后再来一个二层循环 看 n - a^2 - b^2 在之前算出来的c^2 + d^2 中查找看出现过没,如果出现过,
说明a^2 + b^2 + c^2 + d^2 == n 是成立的。

至于上面用的查找,为了加快速度可以用二分来进行查找    
// 用map存储的

#include<iostream>
#include<unordered_map>
using namespace std;
int n,m;
unordered_map<int,pair<int,int>> p;


int main(){
    
    cin>>n;
    
    for (int c = 0 ;c * c <= n; ++c)
        for (int d = c; d * d + c * c <= n; ++d)
            if (p.count(c * c + d * d) == 0)
                p[c * c + d * d] = {c,d};
    
    
    
    for (int a = 0; a * a <= n; ++a)
        for (int b = a; b * b + a * a <= n; ++b){
            
            int t = n - a * a - b * b;
            
            if (p.count(t) != 0){
                cout<<a <<" "<< b <<" "<< p[t].first <<" "<<p[t].second<<endl;
                return 0;
            }    
        }
    
    return 0;
}
// 用到了二分查找的

#include<iostream>
#include<algorithm>
using namespace std;
int n,m;

struct e{
    int c,d;
    int s;
    
    bool operator < (const e & t) const{
        if (t.s != s) return t.s > s;
        if (t.c != c) return t.c > c;
        if (t.d != d) return t.d > d;
    }
}f[5000010];



int main(){
    
    cin>>n;
    
    for (int c = 0 ;c * c <= n; ++c)
        for (int d = c; d * d + c * c <= n; ++d)
            f[m++] = {c,d,c * c + d * d};
    
    sort(f,f + m);
    
    
    
    for (int a = 0; a * a <= n; ++a)
        for (int b = a; b * b + a * a <= n; ++b){
            
            int t = n - a * a - b * b;
            
            int l = 0, r = m - 1;
            while(l < r){
                int mid = l + r >> 1;
                if (f[mid].s >= t) r = mid;
                else l = mid + 1;
            }
            
            if (f[l].s == t){
                cout<<a <<" "<< b <<" "<< f[l].c <<" "<<f[l].d<<endl;
                return 0;
            }    
        }
    
    return 0;
}
发布了341 篇原创文章 · 获赞 32 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_41514525/article/details/103548437
今日推荐