Acwing 1221. 四平方和

 N <= 5e6
a,b,c,d 都是<=N^1/2  每个数 0<= x <= 2200 左右
所以最多枚举2个数, 2200^2 , 三个数就 2200^3 = 8e9 所以最多2个
1. 最多只能枚举两个数
2. 如果可以枚举三个数 d = (N-a^2-b*2-c^2)^1/2
3. 所以需要考虑使用空间来换取时间
4. 本来需要枚举三重循环,但考虑到可能会TLE,先把两重循环的结果存下来(即将所有的c^2+d^2存起来)然后再枚举 a 和 b

for(a)
    for(b=a;a^2+b^2<=n;b++)
    {
        int d = n-a^2-b^2;
        if (check(d)) ok
        else continue;
    }
check(d) 的时候可以二分

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

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()
{
    scanf("%d", &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 = a; 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;
}

本题也可以用哈希表,但是这种解法好像超时了......

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <unordered_map>

using namespace std;

typedef pair<int, int> PII;

int n, m;
unordered_map<int, PII> S;

int main()
{
    scanf("%d", &n);
    
    for (int c = 0; c * c <= n; ++ c)
        for (int d = c; c * c + d * d <= n; ++ d)
        {
            int t = c * c + d * d;
            if (S.count(t) == 0) S[t] = {c, d};
        }    
        
    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;
            if (S.count(t))
            {
                printf("%d %d %d %d\n", a, b, S[t].first, S[t].second);
                return 0;
            }
        }
    }
    
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青衫客36

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值